Python:获取非零退出码命令行的输出

8 投票
3 回答
23158 浏览
提问于 2025-04-16 11:56

我在一台运行 Windows Server 2008 R2 x64 的机器上使用 Python 2.7.1

我想获取一个命令行程序的输出,但这个程序在输出我需要的信息后返回了一个非零的退出状态。

我最开始使用的是 subprocess.check_output,并捕获了因为非零退出状态而产生的 CalledProcessError 错误,但错误中虽然存储了返回码,却没有显示任何输出。

对于那些输出正常但退出状态为 0 的情况,运行是没问题的,我可以通过 subprocess.check_output 获取到输出。

我猜测输出是写入了标准输出(STDOUT),但异常却从标准错误(STDERR)中提取了“输出”。我尝试重新实现 check_output 的功能,但在我认为应该看到标准输出和标准错误的输出时,仍然什么都没有。下面是我当前的代码(其中 'command' 是我运行的命令的完整文本,包括参数):

process = subprocess.Popen(command, stdout=subprocess.PIPE, 
stderr=subprocess.STDOUT, universal_newlines=True)
output = process.communicate()
retcode = process.poll()
if retcode:
    raise subprocess.CalledProcessError(retcode, image_check, output=output)
    return output 

这让我在变量 output 中得到了以下内容: [('', None)]

我的 subprocess.Popen 代码是正确的吗?

3 个回答

1

这里有一个可能会影响到你的问题——http://bugs.python.org/issue9905

3

你有没有试过用 stderr=subprocess.STDOUT,这个在Python的文档页面上提到过:

如果你想把标准错误也一起捕获到结果中,可以使用 stderr=subprocess.STDOUT:

下面是一个测试代码:

import subprocess

try:
    subprocess.check_output('>&2 echo "errrrr"; exit 1', shell=True)
except subprocess.CalledProcessError as e:
    print 'e.output: ', e.output


try:
    subprocess.check_output('>&2 echo "errrrr"; exit 1', shell=True, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
    print 'e.output: ', e.output

输出结果:

errrrr
e.output:  
e.output:  errrrr
10

你的代码运行得很好。结果发现,你调用的那个过程可能是输出到 CON(控制台)。看看下面这个例子:

import subprocess

def check_output(command):
    process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
    output = process.communicate()
    retcode = process.poll()
    if retcode:
            raise subprocess.CalledProcessError(retcode, command, output=output[0])
    return output 

command = "echo this>CON"

print "subprocess -> " + subprocess.check_output(command, shell=True)
print "native -> " + str(check_output(command))

try:
    subprocess.check_output("python output.py", shell=True)
except subprocess.CalledProcessError, e:
    print "subproces CalledProcessError.output = " + e.output

try:
    check_output("python output.py")
except subprocess.CalledProcessError, e:
    print "native CalledProcessError.output = " + e.output

输出结果:

subprocess -> 
native -> ('', None)
stderr subproces CalledProcessError.output = stdout
native CalledProcessError.output = stderr stdout

可惜,我不知道怎么解决这个问题。注意,subprocess.check_output 的结果只包含标准输出(stdout)的内容。而你替代的 check_output 会同时输出标准错误(stderr)和标准输出(stdout)。

经过检查,subprocess.check_output 确实会生成一个 CalledProcessError,并且输出只包含标准输出的内容。

撰写回答