Subprocess.Popen在解释器和可执行脚本中表现不同

3 投票
1 回答
1493 浏览
提问于 2025-04-16 12:04

假设你有以下内容:

command = shlex.split("mcf -o -q -e -w %s %s" % (SOLFILE, NETFILE))
task = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = task.communicate()
print "stdout: %s" % stdout #debugging
print "stderr: %s" % stderr #debugging
if stderr:
    sys.exit("MCF crashed on %s" % NETFILE)

这里的mcf是一个C程序,如果没有给它一个合适的netfile,它就会出现溢出的问题。你可能会问,为什么我不能确保所有的netfiles都是合适的呢?其实,检查这一点最简单的方法就是把它交给mcf,然后看看它是否会溢出……

无论如何,当我在一个可执行的脚本中运行这个程序时,task.communicate()似乎没有在标准输出(stdout)和标准错误(stderr)中存储任何内容。具体来说,我得到的结果是stdout和stderr都是空的('')。相反,mcf的错误输出似乎直接“泄漏”到终端,而不是通过子进程的管道捕获到。下面是一些示例输出来说明这个问题:

Netfile: facility3cat_nat5000_wholesaler_capacitation_test_.net
Solfile: facility3cat_nat5000_wholesaler_capacitation_test_.sol
*** buffer overflow detected ***: mcf terminated
======= Backtrace: =========
...
...[fifty lines of Linda Blair-esque output]...
...
stdout: None
stderr: 
...[program continues, since stderr did not evaluate to True]...

这个问题只在从命令行运行脚本时出现。当我在解释器中逐行执行时,stdout和stderr都能正确赋值:

>>> task = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> stdout, stderr = task.communicate()
>>> stderr
'*** buffer overflow detected ***: mcf terminated\n======= Backtrace: =========\n'
...[more headspinning and vomit]...

有没有人能帮我理解为什么在解释器中能正常工作,但在执行时却不行呢?提前谢谢大家!

1 个回答

1

我写了一个小测试脚本,用来测试一下 subprocess 模块。

#!/bin/bash

echo echo to stderr 1>&2
echo echo to stdout

然后我又写了一个小的 Python 脚本来调用它:

#!/usr/bin/python

import subprocess

command = ('./joe.sh',)
task = subprocess.Popen(command, stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE)
stdout, stderr = task.communicate()
print 'stdout == %r\nstderr == %r' % (stdout, stderr)

运行这个脚本的输出结果看起来就是这样:

$ python joe.py 
stdout == 'echo to stdout\n'
stderr == 'echo to stderr\n'

ipython 中运行同样的代码,输出结果也是一样的。

所以 subprocess 模块的表现是你所期待的,而不是你在提问时遇到的那种情况。我觉得问题可能不在 subprocess 模块上,因为我这边的代码是可以正常工作的。

我使用的是 Python 2.7,所以还有一种可能性是,旧版本的 subprocess 模块可能存在一些奇怪的bug。

撰写回答