【问题标题】:subprocess.check_output return codesubprocess.check_output 返回码
【发布时间】: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.

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

【问题讨论】:

    标签: python subprocess


    【解决方案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)

      【讨论】:

      • 请阅读stackoverflow.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

      【讨论】:

        猜你喜欢
        • 2014-11-03
        • 1970-01-01
        • 1970-01-01
        • 2020-10-01
        • 2018-10-24
        • 1970-01-01
        • 2019-04-18
        • 2015-05-04
        • 2022-01-15
        相关资源
        最近更新 更多