【发布时间】:2014-11-05 00:11:17
【问题描述】:
我想使用subprocess.Popen来运行一个进程,要求如下。
我想在进程运行时将
stdout和stderr传回Popen的调用者。如果进程仍在运行,我想在
timeout秒后终止该进程。
我得出的结论是,subprocess API 中的一个缺陷意味着它不能同时满足这两个要求。考虑以下玩具程序:
chatty.py
while True:
print 'Hi'
silence.py
while True:
pass
caller.py
import subprocess
import time
def go(command, timeout=60):
proc = subprocess.Popen(command, shell=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
start = time.time()
while proc.poll() is None:
print proc.stdout.read(1024) # <----- Line of interest
if time.time() - start >= timeout:
proc.kill()
break
else:
time.sleep(1)
考虑上面的标记线。
如果包含它,
go('python silence.py')将永远挂起 - 而不仅仅是 60 秒 - 因为read是一个阻塞调用,直到1024字节或流结束,并且两者都不会出现。如果被注释,
go('python chatty.py')将一遍又一遍地打印出'Hi',但它如何在生成时流回?proc.communicate()阻塞直到流结束。
我会很高兴有一个解决方案将上述要求 (1) 替换为“在未发生超时的情况下,我希望在算法完成后获得 stdout 和 stderr。”即使这样也有问题。我的实现尝试如下。
speech.py
for i in xrange(0, 10000):
print 'Hi'
caller2.py
import subprocess
import time
def go2(command, timeout=60):
proc = subprocess.Popen(command, shell=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
start = time.time()
while True:
if proc.poll() is not None:
print proc.communicate()
break
elif time.time() - start >= timeout:
proc.kill()
break
else:
time.sleep(1)
但即使这样仍然有问题。即使python speech.py 只运行了几秒钟,go2('python speech.py') 也需要整整 60 秒。这是因为在speech.py 中对print 'Hi' 的调用是阻塞的,直到进程被终止时调用proc.communicate()。由于proc.stdout.read 之前用silence.py 演示过这个问题,我真的不知道如何让它工作。
如何同时获得stdout 和stderr 以及超时行为?
【问题讨论】:
标签: python python-2.7 subprocess