Python subprocess.check_output stderr 用法

4

你好,我是Python的新手,正在尝试理解如何在subprocess check_output中使用stderr。我已经阅读了subprocess文档,但很难理解stderr的使用方式以及subprocess.STDOUT实际完成的具体内容。

请问是否可以提供一些示例或参考资料来解释在此处如何使用stderr?

我已经尝试使用stderr和不使用stderr命令,并没有看到任何真正的区别。

代码:

#!/usr/bin/python3
import subprocess

print(subprocess.check_output("echo Hello World!",
                              stderr=subprocess.STDOUT,
                              shell=True))

输出:

# ./ex.py
b'Hello World!\n'

代码:

#!/usr/bin/python3
import subprocess

print(subprocess.check_output("gecho Hello World!",
                              stderr=subprocess.STDOUT,
                              shell=True))

输出:

# ./ex.py
Traceback (most recent call last):
  File "./ex.py", line 6, in <module>
    shell=True))
  File "/usr/lib64/python3.3/subprocess.py", line 589, in check_output
    raise CalledProcessError(retcode, process.args, output=output)
subprocess.CalledProcessError: Command 'gecho Hello World!' returned non-zero exit status 127

1
您得到了一个CalledProcessError,原因是返回代码为非零值,所有的stderr=subprocess.STDOUT都在将stderr重定向到stdout,它与捕获Python代码中的错误无关。 如果您没有将stderr重定向到stdour,那么任何来自stderr的内容都将被输出到屏幕上,而不会被check_output捕获。 当您想使用stderr = subprocess.STDOUT时,这就是一个示例http://stackoverflow.com/questions/39917569/why-doesnt-this-regex-work/39917623#39917623。 - Padraic Cunningham
@PadraicCunningham 我该如何读取被定向到stderr或重定向到stdout的内容?将其重定向到stdout有什么必要吗?谢谢。 - MBasith
你知道 stderr 和 stdout 是什么吗?https://dev59.com/xXA75IYBdhLWcg3wRWyc。在链接中运行 check_output 代码,一次使用 stderr=subprocess.STDOUT,一次不使用,你会很清楚地看到它们之间的区别。 - Padraic Cunningham
1
@PadraicCunningham 这个链接正是我所需要的。是的,我一开始并没有完全理解它们的含义。非常有帮助。谢谢。 - MBasith
让我们在聊天中继续这个讨论 - MBasith
显示剩余3条评论
1个回答

4

subprocess.check_output函数会在退出码非零时抛出异常。看起来你想要的是一种简单的读取STDERR的方法,这种情况下最简单的方式是使用subprocess.run函数并将STDOUT和STDERR进行管道传输(Windows示例):

>>> p = subprocess.run(['cmd','/C','echo','hello','world'], stdout = subprocess.PIPE, stderr=subprocess.PIPE)
>>> p.stdout
b'hello world\r\n'

>>> p.stderr
b''

>>> p = subprocess.run(['cmd','/C','gecho','hello','world'], stdout = subprocess.PIPE, stderr=subprocess.PIPE)
>>> p.stdout
b''

>>> p.stderr
b"'gecho' is not recognized as an internal or external command,\r\noperable program or batch file.\r\n"

如果你确实需要使用check_output,以下代码将忽略echo调用的错误代码,仍然会打印出错误信息(示例几乎直接引用自文档):
>>> print(subprocess.check_output('gecho hello& exit 0', stderr=subprocess.STDOUT, shell=True))
b"'gecho' is not recognized as an internal or external command,\r\noperable program or batch file.\r\n"

或者在Linux中:

>>> print(subprocess.check_output('gecho hello; exit 0', stderr=subprocess.STDOUT, shell=True))
b'/bin/sh: 1: gecho: not found\n'

作为旁注,使用带有选项 shell=True 的子进程函数几乎从来都不是一个好主意。这主要是出于安全方面的考虑;请阅读文档以获得完整解释。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接