python check_output失败,退出状态为1,但Popen适用于同一命令

时间:2015-02-23 13:42:03

标签: python subprocess popen

指定框架以确定Xcode是否在Mac上运行:cmd = "ps -ax | grep -v grep | grep Xcode"

如果Xcode未运行,则上述命令适用于Popen模块的subprocess方法,但使用CalledProcessError方法引发check_output。我尝试通过以下代码检查stderr,但未能获得适当的信息以了解原因。

from subprocess import check_output, STDOUT, CalledProcessError

psCmd = "ps -ax | grep -v grep | grep Xcode"
o = None
try:
    o = check_output(psCmd, stderr=STDOUT, shell=True)
except CalledProcessError as ex:
    print 'Error:', ex, o

异常消息如下:

Error: Command 'ps -ax | grep -v grep | grep Xcode' returned non-zero exit status 1 None

问题:为什么上面的命令适用于Popen,但是使用check_output失败了?

注意:如果Xcode正在运行,命令适用于这两种方法。

4 个答案:

答案 0 :(得分:18)

check_output()按预期工作。这是Popen()

的简化实现
def check_output(cmd):
    process = Popen(cmd, stdout=PIPE)
    output = process.communicate()[0]
    if process.returncode != 0:
        raise CalledProcessError(process.returncode, cmd, output=output)
    return output

grep如果找不到任何内容,则返回1,例如,如果Xcode未运行,您应该会发现异常。

注意:正如实现所示,即使发生异常,您也可以获得输出:

#!/usr/bin/env python
from subprocess import check_output, STDOUT, CalledProcessError

cmd = "ps -ax | grep -v grep | grep Xcode"
try:
    o = check_output(cmd, stderr=STDOUT, shell=True)
    returncode = 0
except CalledProcessError as ex:
    o = ex.output
    returncode = ex.returncode
    if returncode != 1: # some other error happened
        raise

您可以改为使用pgrep -a Xcode命令(注意:以p开头)或使用psutil模块获取可移植代码:

#!/usr/bin/env python
import psutil # $ pip install psutil

print([p.as_dict() for p in psutil.process_iter() if 'Xcode' in p.name()])

答案 1 :(得分:2)

从Python文档:“如果返回代码非零,则会引发CalledProcessError。”这就是当Xcode没有运行时你会发生什么;最终grep Xcode退出时状态为非零,因为grep无法找到您要查找的字符串Xcode。因此,check_output()将引发异常。

顺便说一句,我在the Python subprocess documentation上找到了这个。

答案 2 :(得分:1)

如果你的grep命令grep Xcode没有返回任何结果,那么命令的returncode将不为零,这就是为什么check_output正在调用CalledProcessError,这就是你正在print命令

的输出中看到

要获得命令的输出,请将错误或成功使用以下代码: -

#!/usr/bin/python
from subprocess import check_output, STDOUT, CalledProcessError

psCmd = "ps -aef | grep -v grep | grep Xcode"
o = None
o = check_output(psCmd+";exit 0", stderr=STDOUT, shell=True)

check_output只会显示命令的输出,如果它的返回码是0,否则它会调用异常。

答案 3 :(得分:0)

check_output的目的是确保您运行的命令成功完成。如果grep Xcode未成功返回,则假设会失败。

无论如何,在Python中搜索你想要的东西会更简单。

output = check_output(['ps', '-ax'], shell=False)
if 'Xcode' in output:
    print('Xcode appears to be running')

如果ps由于某种原因失败,那么它比shell版本具有额外的(非常小的)优势,它实际上失败了。如果ps的退出代码不在管道的末尾,它就会忽略它。