【问题标题】:subprocess.check_output(): show output on failuresubprocess.check_output():失败时显示输出
【发布时间】:2014-06-25 08:23:59
【问题描述】:

subprocess.check_output() 的输出此刻看起来像这样:

CalledProcessError: Command '['foo', ...]' returned non-zero exit status 1

有没有办法获得更好的错误信息?

我想看看stdoutstderr

【问题讨论】:

标签: python subprocess


【解决方案1】:

STDERR 重定向到STDOUT

示例 来自解释器

>>> try:
...   subprocess.check_output(['ls','-j'], stderr=subprocess.STDOUT)
... except subprocess.CalledProcessError as e:
...   print('error>', e.output, '<')
...

error> b"ls: invalid option -- 'j'\nTry `ls --help' for more information.\n" <

解释

来自check_output 文档:

要在结果中同时捕获标准错误,请使用 stderr=subprocess.STDOUT

【讨论】:

  • 您是在此处捕获 STDOUT 还是 STDERR?
  • 对我来说这很有效——我只需要打印异常输出即可得到我想要的(命令的失败文本,同时仍然捕获异常)。
【解决方案2】:

由于不想写更多代码,只是为了得到一个好的错误信息,我写了subx

来自文档:

subprocess.check_output() 与 subx.call()

查看、比较、思考并决定哪些信息对您更有帮助。

subprocess.check_output()::

CalledProcessError: Command '['cat', 'some-file']' returned non-zero exit status 1

sub.call()::

SubprocessError: Command '['cat', 'some-file']' returned non-zero exit status 1:
stdout='' stderr='cat: some-file: No such file or directory'

... 特别是如果代码在生产环境中失败 重现错误并不容易,subx 可以调用帮助您发现 失败的根源。

【讨论】:

    【解决方案3】:

    在我看来这是使用sys.excepthook 的完美场景!您只需在if 语句中过滤您想要格式化的内容。使用此解决方案,它将覆盖您代码的所有异常,而无需折射所有内容!

    #!/usr/bin/env python
    import sys
    import subprocess
    
    # Create the exception handler function
    def my_excepthook(type, value, traceback):
        # Check if the exception type name is CalledProcessError
        if type.__name__ == "CalledProcessError":
            # Format the error properly
            sys.stderr.write("Error: " + type.__name__ + "\nCommand: " + value.cmd + "\nOutput: " + value.output.strip())
        # Else we format the exception normally
        else:
            sys.stderr.write(str(value))
    
    # We attach every exceptions to the function my_excepthook
    sys.excepthook = my_excepthook
    
    # We duplicate the exception
    subprocess.check_output("dir /f",shell=True,stderr=subprocess.STDOUT)
    

    您可以根据需要修改输出,这是实际输出:

    Error: CalledProcessError
    Command: dir /f
    Output: Invalid switch - "f".
    

    【讨论】:

    • 这会改变全局内容,这些内容会影响在调用上述问题的行数小时后执行的代码。是的,您的解决方案有效,但我更喜欢不进行全局更改的解决方案。我的图书馆有问题。我想在这个级别解决这个问题。 (例如使用替代库)。
    【解决方案4】:

    不要使用check_output(),而是使用PopenPopen.communicate()

    >>> proc = subprocess.Popen(['cmd', '--optional-switch'])
    >>> output, errors = proc.communicate()
    

    这里output 是来自stdout 的数据,errors 是来自stderr 的数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-27
      • 1970-01-01
      • 2023-01-27
      • 2014-12-04
      • 1970-01-01
      • 1970-01-01
      • 2016-10-19
      相关资源
      最近更新 更多