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

发布于 2024-10-18 05:31:04 字数 1440 浏览 1 评论 0原文

假设您有以下内容:

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]...

任何人都可以帮助我理解为什么这在解释器中有效,但在执行时却不起作用?提前致谢!

Let's say you have the following:

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)

It's not necessary to know what mcf is, except that it's a C program which will overflow if it's not given a satisfiable netfile. (Why can't I just ensure that all the netfiles are satisfiable? Well, because the easiest way to check that is to feed it to mcf and see if it overflows...)

Anyway, when I run this in an executable script, task.communicate() doesn't seem to store anything in stdout and stderr. (To be precise, I get stdout == stderr == ''.) Instead, the stderr stream from mcf seems to be "leaking" to the terminal rather than getting captured by the subprocess pipe. Here's some sample output to illustrate:

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]...

This only fails when running the script from the command line. When I step through it line by line in the interpreter, stdout and stderr are correctly assigned:

>>> 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]...

Could anyone help me to understand why this works in the interpreter, but not when executed? Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

风向决定发型 2024-10-25 05:31:04

我编写了一个小测试脚本来测试 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 模块中可能存在某种奇怪的错误。

I wrote a little test script to test the subprocess module with.

#!/bin/bash

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

Then I wrote a small Python script that calls it:

#!/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)

The output of running it looks just like this:

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

The output of running that same sequence in ipython is the same.

So the subprocess module is behaving in the manner you expect, and not how it's behaving for you in your question. I think something other than the subprocess module must be at fault here because what you're doing works for me.

I'm running Python 2.7, so another possibility is that maybe there is some kind of weird bug in older versions of the subprocess module.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文