需要避免子进程死锁而不使用 communicate
我需要执行一个命令,这个命令会产生很多输出,并且执行时间很长(超过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
- 为了绕过Python的一个bug #1124861,在Python2.4中,你可以把
stdin
(标准输入)连接到一个NUL
设备上。
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()