我阅读了subprocess提供的函数 - call,check_call,check_output,并了解每个函数的工作方式和功能之间的差异。我目前正在使用check_output,所以我可以访问stdout,并使用“try block”来捕获异常,如下所示:
# "cmnd" is a string that contains the command along with it's arguments.
try:
cmnd_output = check_output(cmnd, stderr=STDOUT, shell=True, timeout=3, universal_newlines=True);
except CalledProcessError:
print("Status : FAIL")
print("Output: \n{}\n".format(cmnd_output))
我遇到的问题是抛出异常时,“cmnd_output”未初始化且无法访问stderr,我收到以下错误消息:
print("Output: \n{}\n".format(cmnd_output))
UnboundLocalError: local variable 'cmnd_output' referenced before assignment
我认为那是因为异常导致“check_output”立即保释而没有任何进一步的处理,也就是在try块中分配给“cmnd_output”。如果我错了,请纠正我。
有什么方法可以访问stderr(如果它被发送到stout就可以了)并且可以访问退出代码。我可以根据退出代码手动检查通过/失败,但不会发生异常。
谢谢你, 艾哈迈德。
答案 0 :(得分:78)
试试这个版本:
import subprocess
try:
output = subprocess.check_output(
cmnd, stderr=subprocess.STDOUT, shell=True, timeout=3,
universal_newlines=True)
except subprocess.CalledProcessError as exc:
print("Status : FAIL", exc.returncode, exc.output)
else:
print("Output: \n{}\n".format(output))
这样,只有在呼叫成功时才会打印输出。
如果是CalledProcessError
,则打印返回代码和输出。
答案 1 :(得分:47)
已接受的解决方案涵盖了您可以混合stdout
和stderr
的情况,但是在子进程(无论出于何种原因)决定使用stderr
的情况下添加对于未失败的输出(即输出非严重警告)到stdout
,那么给定的解决方案可能是不可取的。
例如,如果你要对输出进行额外的处理,比如转换为JSON,然后混合stderr
,则整个过程将失败,因为输出不是纯JSON,因为添加了stderr
输出。
我发现以下情况可以解决这个问题:
cmd_args = ... what you want to execute ...
pipes = subprocess.Popen(cmnd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
std_out, std_err = pipes.communicate()
if pipes.returncode != 0:
# an error happened!
err_msg = "%s. Code: %s" % (std_err.strip(), pipes.returncode)
raise Exception(err_msg)
elif len(std_err):
# return code is 0 (no error), but we may want to
# do something with the info on std_err
# i.e. logger.warning(std_err)
# do whatever you want with std_out
# i.e. json.loads(std_out)
答案 2 :(得分:3)
两种建议的解决方案要么混合使用stdout / stderr,要么使用Popen
,它不像check_output
那么简单。但是,你可以完成同样的事情,并且在使用check_output
的情况下保持stdout / stderr分开,如果你只是使用管道捕获stderr :
import sys
import subprocess
try:
subprocess.check_output(cmnd, stderr=subprocess.PIPE)
except subprocess.CalledProcessError as e:
print('exit code: {}'.format(e.returncode))
print('stdout: {}'.format(e.output.decode(sys.getfilesystemencoding())))
print('stderr: {}'.format(e.stderr.decode(sys.getfilesystemencoding())))
在这个例子中,由于我们捕获了stderr,它在异常stderr
属性中可用(没有使用管道捕获,它只是None
)。< / p>
答案 3 :(得分:0)
我有类似的要求,以下对我有用:
try:
with open ("vtcstderr.out", "w") as file:
rawOutput = subprocess.check_output(
command,
stderr=file,
shell=True
)
except subprocess.CalledProcessError as error:
# this is the stdout
rawOutput = error.output
with open ("vtcstderr.out", "r") as file:
# this is the stderr
errorLines = file.readlines()
答案 4 :(得分:-2)
为什么不在try语句之前初始化变量cmnd_output?这样它就会按照你期望的方式工作。 以下行可行,只需将其添加到try语句上方:
cmnd_output = ''