【问题标题】:Redirect subprocess stderr to stdout将子进程 stderr 重定向到 stdout
【发布时间】:2012-07-14 19:08:21
【问题描述】:

我想将子进程的标准错误输出重定向到标准输出。常量STDOUT 应该这样做,不是吗?

然而,

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

确实输出了一些东西。为什么会这样,我如何在标准输出上得到错误信息?

【问题讨论】:

标签: python stderr subprocess


【解决方案1】:

仔细阅读source code 给出了答案。特别是,documentation 在以下内容时具有误导性:

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

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

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

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

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

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

【讨论】:

  • 也可以保持标准错误:stderr=sys.stderr.fileno()。很好的例子;我将在我的所有脚本中简单地使用这种技术。我们有旧版 Python 2.x;因此我会准确地知道我告诉它去哪里,而不会混淆。
  • 作为记录,这在 python 3.5+ 中不再需要,因为这种情况会自动处理:github.com/python/cpython/blob/…
【解决方案2】:

实际上,使用 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,这是一个主要的区别。

【讨论】:

  • -1 这种情况与stdoutNone 的问题无关。并且subprocess.STDOUT 不会重定向到“调用控制台”(我认为您的意思是给定当前进程的文件句柄 1),如您自己的示例所示 - 如果您使用['ls', '/404'] 调用 Popen,则 error message is not displayed
  • 你说得对。但是,我认为这根本不是无关紧要的,因为这是为了澄清您关于文档具有误导性的帖子 - 事实并非如此。我本来可以在你的帖子下方发表评论,但一年前我不被允许这样做。
  • python -c 'import subprocess,sys;subprocess.call(["ls", "/404"], stderr=subprocess.STDOUT)' 2>/dev/null 显示ls 的stderr 转到stderr(文件描述符2),因为您将看不到任何输出(假设您的系统上没有/404)。那个 Python 文档真的对那个话题很感兴趣,这对我们这些习惯于以各种方式操作 stdout/stderr 的 shell 脚本编写者来说尤其烦人,他们不得不来到这里只是为了弄清楚如何做一些应该简单的事情不混淆。
  • 在我看来,以上是更简单的解决方案和OP的意图。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-22
  • 1970-01-01
  • 2015-08-18
  • 2022-01-18
  • 2011-07-18
  • 1970-01-01
  • 2012-08-07
相关资源
最近更新 更多