我想将子进程的stderr输出重定向到stdout。常量STDOUT
应该可以做到这一点,是吗?
但是,
$ python >/dev/null -c 'import subprocess;\
subprocess.call(["ls", "/404"],stderr=subprocess.STDOUT)'
为什么会输出一些东西。为什么会这样,我该如何在标准输出中获取错误信息?
我想将子进程的stderr输出重定向到stdout。常量STDOUT
应该可以做到这一点,是吗?
但是,
$ python >/dev/null -c 'import subprocess;\
subprocess.call(["ls", "/404"],stderr=subprocess.STDOUT)'
为什么会输出一些东西。为什么会这样,我该如何在标准输出中获取错误信息?
在 Python < v3.5 中:
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;因此,我会清楚地知道我告诉它去哪里而没有混淆。 - Mike S实际上,使用subprocess.STDOUT
的作用就是按照文档所述将stderr重定向到stdout以便处理。
command = ["/bin/ls", "/tmp", "/notthere"]
process = subprocess.Popen(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 = process.stdout.readline()
line = line.decode()
if (line == ""): break
output += line
结果存储在变量output
中,其中包括进程从标准输出和标准错误输出获得的内容。
stderr=subprocess.STDOUT
将所有标准错误输出直接重定向到调用进程的标准输出上,这是一个主要区别。
编辑: 为更新的Python版本更新了代码:
command = ["/bin/ls", "/tmp", "/notthere"]
process = subprocess.Popen(command, shell=False, text=True, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
output = ""
while (True):
# Read line from stdout, break if EOF reached, append line to output
line = process.stdout.readline()
if (line == ""): break
output += line
stdout
为 None
。而且 subprocess.STDOUT
并不会重定向到“调用控制台”(我想你指的是当前进程所给出的文件句柄1),正如你自己的示例所显示的那样 - 如果你使用 ['ls', '/404']
调用 Popen,则错误消息不会被显示。 - phihagpython -c 'import subprocess,sys;subprocess.call(["ls", "/404"], stderr=subprocess.STDOUT)' 2>/dev/null
显示 ls
的 stderr 转到 stderr(文件描述符 2),因为您不会看到任何输出(假设您的系统上没有 /404
)。Python 文档在这个主题上真的很糟糕,对于我们这些习惯于以无数种方式操作 stdout/stderr 的 shell 脚本编写者来说,这尤其令人恼火,我们必须来到 SO 这里才能弄清楚如何做一些简单而不会混淆的事情。 - Mike S