将子流程stderr重定向到stdout

phi*_*hag 37 python subprocess stderr

我想将子进程的stderr输出重定向到stdout.常数STDOUT应该这样做,不应该吗?

然而,

$ python >/dev/null -c 'import subprocess;\
                        subprocess.call(["ls", "/404"],stderr=subprocess.STDOUT)'
Run Code Online (Sandbox Code Playgroud)

输出的东西.为什么会这样,我如何在stdout上收到错误消息?

phi*_*hag 35

仔细阅读源代码就可以得到答案.特别是,文档说它时会产生误导:

subprocess.STDOUT
特殊值(...)表示标准错误应与标准输出进入同一句柄.

由于stdout -1stderr=subprocess.STDOUT评估时设置为"default"(技术上),因此stderr也设置为"default".不幸的是,这意味着stderr输出仍然转到stderr.

要解决此问题,请传入stdout文件而不是subprocess.STDOUT:

$ python >/dev/null -c 'import subprocess,sys;subprocess.call(["ls", "/404"],
                        stderr=sys.stdout.buffer)'
Run Code Online (Sandbox Code Playgroud)

或者,为了与遗留的2.x版本的Python兼容:

$ python >/dev/null -c 'import subprocess,sys;subprocess.call(["ls", "/404"],
                        stderr=sys.stdout.fileno())'
Run Code Online (Sandbox Code Playgroud)

  • 也可以将stderr保持不变:`stderr = sys.stderr.fileno()`。很好的例子;我将在所有脚本中简单使用此技术。我们有旧版Python 2.x;因此,我会确切知道我告诉它去的地方而不会引起混乱。 (2认同)
  • 根据记录,这在 python 3.5+ 中不再需要,因为这种情况会自动处理:https://github.com/python/cpython/blob/75c1ca7b6c546ef674eb40bfe47f41e6045dc99b/Lib/subprocess.py#L1143-L1147 (2认同)

Max*_*xim 16

其实用subprocess.STDOUT究竟是什么的文件中指出:它重定向标准错误到标准输出,使得例如

proc = subprocess.Popen(self.task["command"], shell=False, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
output = ""
while (True):
    # Read line from stdout, break if EOF reached, append line to output
    line = proc.stdout.readline()
    line = line.decode()
    if (line == ""): break
    output += line
Run Code Online (Sandbox Code Playgroud)

导致变量output包含stdout和stderr的进程输出.

stderr=subprocess.STDOUT将所有stderr输出直接重定向到调用进程的stdout,这是一个主要区别.

  • -1 这种情况与关于 `stdout` 为 `None` 的问题无关。并且 `subprocess.STDOUT` 不会重定向到“调用控制台”(我认为您的意思是当前进程给出的文件句柄 1),如您自己的示例所示 - 如果您使用 `['ls', ' 调用 Popen /404']`,[错误信息不显示](http://ideone.com/2JhcRT)。 (2认同)
  • 在我看来,以上是更简单的解决方案和OP的意图。 (2认同)