Subprocess.Popen在解释器,可执行脚本中的行为不同

时间:2011-02-18 16:27:40

标签: python subprocess

假设您有以下内容:

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程序,如果它没有给出令人满意的网络文件会溢出。 (为什么我不能确保所有的netfiles都可以满足?嗯,因为检查它的最简单方法是将它提供给mcf并查看它是否溢出......)

无论如何,当我在可执行脚本中运行它时,task.communicate()似乎不会在stdout和stderr中存储任何内容。 (确切地说,我得到stdout == stderr ==''。)相反,来自mcf的stderr流似乎“泄漏”到终端而不是被子进程管道捕获。以下是一些示例输出来说明:

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 个答案:

答案 0 :(得分: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模块的旧版本中可能存在某种奇怪的错误。