需要避免子进程死锁而不使用 communicate

22 投票
5 回答
10398 浏览
提问于 2025-04-16 15:17

我需要执行一个命令,这个命令会产生很多输出,并且执行时间很长(超过30分钟)。我在考虑使用subprocess.Popen来实现这个功能。我需要捕获这个命令的输出,所以我把stdout和stderr都设置为PIPE。

在很多论坛上,关于使用Popen.wait()时会出现死锁的问题已经有很多讨论,所以大家建议使用Popen.communicate()来避免死锁。不过,这个方法的问题在于,communicate()会一直等到命令执行完才会返回。我需要在命令执行的过程中,实时打印所有到达的stdout输出。如果20分钟后没有输出,脚本就会被强制终止。

这里有一些我需要遵守的限制:

  • 我的Python版本是2.4.2,无法升级。
  • 如果解决方案还是要用subprocess,我需要把subprocess.PIPE传给所有标准句柄,以避免这个bug:http://bugs.python.org/issue1124861

有没有办法做到这一点呢?

5 个回答

3

听起来你需要对连接到管道的文件句柄进行非阻塞读取。

这个问题讨论了一些在Windows和Linux上实现这个功能的方法:在Python中对subprocess.PIPE进行非阻塞读取

6

你试过 pexpect 吗?

13

import os
from subprocess import PIPE, STDOUT, Popen

lines = []
p = Popen(cmd, bufsize=1, stdin=open(os.devnull), stdout=PIPE, stderr=STDOUT)
for line in iter(p.stdout.readline, ''):
      print line,          # print to stdout immediately
      lines.append(line)   # capture for later
p.stdout.close()
p.wait()

撰写回答