【问题标题】:Subprocess.Popen behaves differently in interpreter, executable scriptsSubprocess.Popen 在解释器、可执行脚本中的行为不同
【发布时间】:2011-02-20 19:11:43
【问题描述】:

假设您有以下内容:

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 程序,如果没有给定一个可满足的网络文件,它将溢出。 (为什么我不能确保所有的网络文件都是可满足的?嗯,因为最简单的检查方法是将它提供给 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]...

谁能帮我理解为什么这在解释器中有效,但在执行时无效?提前致谢!

【问题讨论】:

  • 修改了我的答案以表明我已经完成了测试。

标签: python subprocess


【解决方案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 模块中可能存在某种奇怪的错误。

【讨论】:

  • 谢谢,我也发现了。修复了帖子以反映这一点。当 stdout 被重定向时,它仍然可以在解释器中工作,并且仍然不能在命令行中。
  • @Omnifarious 是的,命令是一样的。事实上,我得到了同样的缓冲区溢出错误,只是在解释器中它被捕获并分配给 stderr,而在命令行它被转储到屏幕上。
  • @W voq - 这很奇怪。我想我很快就会删除我的答案,因为我不知道这是怎么回事。它适用于我写的一个小 shell 脚本,它把东西吐到 stdoutstderr
  • @Omnifarious 感谢您为此提供的所有帮助。我接受了你的回答,因为它帮助我确定它是被调用的进程,而不是泄漏的子进程模块。
  • @wvoq:我认为是这样的。我提供了详细的演示,这样你就有一个很好的诊断工具来解决这个问题。我很高兴它有帮助。 :-)
猜你喜欢
  • 1970-01-01
  • 2020-06-22
  • 2011-09-20
  • 2014-01-15
  • 1970-01-01
  • 1970-01-01
  • 2013-04-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多