这是我的代码,它启动一个子进程,等待它结束并返回stdout,或者发生超时并引发异常。常用的是print(Run('python --version').execute())
class Run(object):
def __init__(self, cmd, timeout=2*60*60):
self.cmd = cmd.split()
self.timeout = timeout
self._stdout = b''
self.dt = 10
self.p = None
def execute(self):
print("Execute command: {}".format(' '.join(self.cmd)))
def target():
self.p = Popen(self.cmd, stdout=PIPE, stderr=STDOUT)
self._stdout = self.p.communicate()[0]
thread = Thread(target=target)
thread.start()
t = 0
while t < self.timeout:
thread.join(self.dt)
if thread.is_alive():
t += self.dt
print("Running for: {} seconds".format(t))
else:
ret_code = self.p.poll()
if ret_code:
raise AssertionError("{} failed.\nretcode={}\nstdout:\n{}".format(
self.cmd, ret_code, self._stdout))
return self._stdout
else:
print('Timeout {} reached, kill task, pid={}'.format(self.timeout, self.p.pid))
self.p.terminate()
thread.join()
raise AssertionError("Timeout")
问题是以下情况。我启动的过程会产生更多的子进程。因此,当达到超时时,我使用self.p.terminate()
杀死主进程(我使用我的类使用的那个),子进程保持不变,我的代码挂在行self._stdout = self.p.communicate()[0]
上。如果我手动终止所有子进程,则继续执行。
我尝试了解析而不是self.p.terminate()
我杀了整个过程树。
如果主进程自己完成并且其子进程本身存在,那么这也不起作用,我无法找到并杀死它们。但他们阻止了self.p.communicate()
。
有没有办法有效解决这个问题?
答案 0 :(得分:0)
你可以使用PySys框架中的ProcessWrapper - 它提供了很多这种功能作为跨平台方式的抽象,即
import sys, os
from pysys.constants import *
from pysys.process.helper import ProcessWrapper
from pysys.exceptions import ProcessTimeout
command=sys.executable
arguments=['--version']
try:
process = ProcessWrapper(command, arguments=arguments, environs=os.environ, workingDir=os.getcwd(), stdout='stdout.log', stderr='stderr.log', state=FOREGROUND, timeout=5.0)
process.start()
except ProcessTimeout:
print "Process timeout"
process.stop()
如果有兴趣,请访问SourceForge(http://sourceforge.net/projects/pysys/files/和http://pysys.sourceforge.net/)。