subprocess.Popen 和缓冲的进程输出

Posted

技术标签:

【中文标题】subprocess.Popen 和缓冲的进程输出【英文标题】:subprocess.Popen and buffered process output 【发布时间】:2011-02-09 16:38:38 【问题描述】:

从 python 代码内部,我想运行一个从标准输入获取参数的二进制程序。使用 subprocess 模块,这应该很简单:

import subprocess
command = [ 'my_program' ]
p = subprocess.Popen( command,  \
        stdin = subprocess.PIPE, stdout = subprocess.PIPE, \
        env= "GFORTRAN_UNBUFFERED_ALL": "1" )
p.stdin.write ( stdin_stuff )
while True:
  o = p.stdout.readline()
  if p.poll() != None: 
    break
  # Do something with stdout

现在,这会启动程序,但 python 脚本只是挂在那里。我知道这很可能是由于 gfortran (我用来编译 my_program 正在缓冲其标准输出流。gfortran 允许使用 GFORTRAN_UNBUFFERED_ALL 环境变量,就像我所做的那样,以及在 fortran 代码中使用 FLUSH() 内在变量,但仍然没有运气:python 代码仍然挂起。

【问题讨论】:

您可以通过“检查”旁边的标记来接受您喜欢的答案。这样做在本网站上被认为是有礼貌的,因此您可能需要在您提出的问题上检查您最喜欢的答案。 【参考方案1】:

使用Popen.communicate() 将字符串发送到进程'stdin 而不是手动写入它应该会有更好的运气。

stdoutdata, stderrdata = p.communicate(stdin_stuff)

【讨论】:

【参考方案2】:

为了补充Aphex's answer,这里是documentation的相关部分:

警告

使用communicate() 而不是.stdin.write.stdout.read.stderr.read 以避免由于任何其他操作系统管道缓冲区填满并阻塞子进程而导致的死锁。

【讨论】:

这可能更好地作为@Aphex 的更新或评论。像这样单独似乎不是一个好的答案。 @S.Lott:考虑过将其设为评论,但格式确实不能用作评论。这就是为什么我明确表示这是对 Aphex 答案的补充。 “格式真的不能作为评论”。真的。为什么不更新? communicateinput 参数是纯字符串,而不是流,因此如果输入数据可能很大,请将其放在生产者线程中。如果输出数据可能很大,从输出增量读取,如this example。

以上是关于subprocess.Popen 和缓冲的进程输出的主要内容,如果未能解决你的问题,请参考以下文章

管道输出subprocess.Popen到文件

“subprocess.Popen” - 检查成功和错误

python中的subprocess.Popen()使用

subprogress模块

后台进程 subprocess.Popen 与管道

python--subprocess,粘包现象与解决办法,缓冲区