subprocess.check_output 返回码

Posted

技术标签:

【中文标题】subprocess.check_output 返回码【英文标题】:subprocess.check_output return code 【发布时间】:2014-06-18 17:10:57 【问题描述】:

我正在使用:

grepOut = subprocess.check_output("grep " + search + " tmp", shell=True)

要运行终端命令,我知道我可以使用 try/except 来捕获错误,但是如何获取错误代码的值?

我在官方文档上找到了这个:

 exception subprocess.CalledProcessError

    Exception raised when a process run by check_call() or check_output() returns a non-zero exit status.

    returncode

        Exit status of the child process.

但没有给出示例,谷歌也没有帮助。

【问题讨论】:

【参考方案1】:

您可以从引发的异常中获取错误代码和结果。

这可以通过returncodeoutput 字段完成。

例如:

import subprocess

try:
    grepOut = subprocess.check_output("grep " + "test" + " tmp", shell=True)                       
except subprocess.CalledProcessError as grepexc:                                                                                                   
    print("error code", grepexc.returncode, grepexc.output)

【讨论】:

谢谢你正是我想要的。但现在我想知道,有没有办法在没有尝试/例外的情况下获得返回码? IE 只是获取 check_output 的返回码,是 0 还是 1 或其他对我来说并不重要,我实际上不需要保存输出。 没问题。不幸的是,只要错误代码不为零,check_output 将始终抛出 CalledProcessError。这意味着如果您不希望程序突然终止,您将需要一个 try/except 子句。但是,如果您不关心错误代码,则可以在进入 except 子句时使用“pass”语句。【参考方案2】:

有没有办法在没有尝试/例外的情况下获得返回码?

check_output 如果收到非零退出状态,则会引发异常,因为这通常意味着命令失败。即使没有错误,grep 也可能返回非零退出状态——在这种情况下,您可以使用 .communicate()

from subprocess import Popen, PIPE

pattern, filename = 'test', 'tmp'
p = Popen(['grep', pattern, filename], stdin=PIPE, stdout=PIPE, stderr=PIPE,
          bufsize=-1)
output, error = p.communicate()
if p.returncode == 0:
   print('%r is found in %s: %r' % (pattern, filename, output))
elif p.returncode == 1:
   print('%r is NOT found in %s: %r' % (pattern, filename, output))
else:
   assert p.returncode > 1
   print('error occurred: %r' % (error,))

您不需要调用外部命令来过滤行,您可以在纯 Python 中完成:

with open('tmp') as file:
    for line in file:
        if 'test' in line:
            print line,

如果你不需要输出;你可以使用subprocess.call():

import os
from subprocess import call
try:
    from subprocess import DEVNULL # Python 3
except ImportError: # Python 2
    DEVNULL = open(os.devnull, 'r+b', 0)

returncode = call(['grep', 'test', 'tmp'], 
                  stdin=DEVNULL, stdout=DEVNULL, stderr=DEVNULL)

【讨论】:

【参考方案3】:

Python 3.5 引入了subprocess.run() 方法。签名看起来像:

subprocess.run(
  args, 
  *, 
  stdin=None, 
  input=None, 
  stdout=None, 
  stderr=None, 
  shell=False, 
  timeout=None, 
  check=False
)

返回的结果是subprocess.CompletedProcess。在 3.5 中,您可以从执行的进程中访问argsreturncodestdoutstderr

例子:

>>> result = subprocess.run(['ls', '/tmp'], stdout=subprocess.DEVNULL)
>>> result.returncode
0

>>> result = subprocess.run(['ls', '/nonexistent'], stderr=subprocess.DEVNULL)
>>> result.returncode
2

【讨论】:

我认为这是最新的方法。语法更加简单和直观,可能正是出于这个原因而添加的。 根据docs.python.org/3/library/subprocess.html#subprocess.run:“如果检查为真,并且进程以非零退出代码退出,则会引发 CalledProcessError 异常。该异常的属性包含参数,退出代码, 以及 stdout 和 stderr(如果它们被捕获)。”【参考方案4】:

要获得输出和返回代码(不带 try/except),只需使用 subprocess.getstatusoutput(需要 Python 3)

【讨论】:

请阅读***.com/help/how-to-answer,了解如何写出好的答案。 完成。现在呢? 这不仅仅是阅读,而是关于在您的答案中实施它。 我想我只是不明白它有什么问题。请告诉我您认为应该如何改进。 你可以提供一个你提到的方法的例子。然而,你的回答让我注意到了另一种我还不知道的方法,所以无论如何它对我来说已经很有价值了。【参考方案5】:

在 Python 2 中 - 使用 commands 模块:

import command
rc, out = commands.getstatusoutput("ls missing-file")
if rc != 0: print "Error occurred: %s" % out

在 Python 3 中 - 使用 subprocess 模块:

import subprocess
rc, out = subprocess.getstatusoutput("ls missing-file")
if rc != 0: print ("Error occurred:", out)

发生错误:ls: cannot access missing-file: No such file or directory

【讨论】:

以上是关于subprocess.check_output 返回码的主要内容,如果未能解决你的问题,请参考以下文章

如何编写 subprocess.check_output 的异步版本?

在 subprocess.check_output() 中抑制 stderr

Python subprocess.check_output()

当父进程死亡时,如何杀死使用 subprocess.check_output() 创建的 python 子进程?

了解python subprocess.check_output的第一个参数和shell = True [重复]

如何从 Python subprocess.check_output() 捕获异常输出?