import subprocess as sub
import threadingclass RunCmd(threading.Thread):def __init__(self, cmd, timeout):threading.Thread.__init__(self)self.cmd = cmdself.timeout = timeoutdef 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 -9self.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