import subprocess as sub
import threading
class RunCmd(threading.Thread):
def __init__(self, cmd, timeout):
threading.Thread.__init__(self)
self.cmd = cmd
self.timeout = timeout
def run(self):
self.p = sub.Popen(self.cmd)
self.p.wait()
def Run(self):
self.start()
self.join(self.timeout)
if self.is_alive():
self.p.terminate() #use self.p.kill() if process needs a kill -9
self.join()
RunCmd(["./someProg", "arg1"], 60).Run()
这个想法是创建一个运行该命令的线程,如果超过某个合适的值(在这种情况下为60秒),则将其杀死。
也可以采用下例中的方式,使用theading.timer类,在subprocess启动的时候,start这个timer,由于timer绑定了kill subprocess事件,当超时的时候,将会把subprocess kill掉。
def run(cmd, timeout_sec):
if (sys.version_info >= (3,5)):
try:
completed = subprocess.run(shlex.split(cmd), timeout=timeout_sec, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
return completed.stdout.decode('utf-8'), completed.stderr.decode('utf-8')
except subprocess.TimeoutExpired:
message = 'Fitting got killed by timeout after '+str(timeout_sec)+' sec!'
print (message)
raise EslException(message)
else:
proc = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
kill_proc = lambda p: p.kill()
timer = Timer(timeout_sec, kill_proc, [proc])
try:
timer.start()
stdout,stderr = proc.communicate()
finally:
timer.cancel()
if (proc.poll() == -9 ):
raise EslException('Fitting probably got killed by timeout!')
#if (proc.poll() != 0 ):
# raise EslException('Fitting crashed! returned '+str(proc.poll()))
return stdout, stderr