subprocess.Popen 和缓冲进程输出

2 投票
2 回答
1275 浏览
提问于 2025-04-16 11:31

我想在Python代码中运行一个二进制程序,这个程序的参数是从标准输入(stdin)获取的。使用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在处理输出流时有缓冲。gfortran允许使用一个叫做GFORTRAN_UNBUFFERED_ALL的环境变量,正如我所做的那样,也可以在Fortran代码中使用FLUSH()这个函数,但还是没用:Python代码依然卡住。

2 个回答

2

为了补充 Aphex的回答,这里是 文档 中相关的部分:

警告

使用 communicate() 方法,而不是 .stdin.write.stdout.read.stderr.read,这样可以避免因为操作系统的管道缓冲区满了而导致的死锁问题,这种情况会阻塞子进程的运行。

4

你可以试试用 Popen.communicate() 这个方法来发送字符串到程序的 stdin,这样比手动写入要好很多。

stdoutdata, stderrdata = p.communicate(stdin_stuff)

撰写回答