将子流程stderr重定向到stdout

时间:2012-07-15 21:33:08

标签: python stderr subprocess

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

然而,

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

输出内容。为什么会出现这种情况,如何在stdout上收到错误消息?

2 个答案:

答案 0 :(得分:35)

仔细阅读source code给出答案。特别是,documentation在说出来时会产生误导:

  

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

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

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

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

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

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

答案 1 :(得分:12)

实际上,使用subprocess.STDOUT确实完全文档中所述的内容:它将stderr重定向到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

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

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