2024-04-26 06:11:51 发布
网友
是否有任何参数或选项来设置Python的subprocess.Popen方法的超时?
像这样的:
subprocess.Popen(['..'], ..., timeout=20)?
subprocess.Popen(['..'], ..., timeout=20)
subprocess.Popen不阻塞,因此您可以执行以下操作:
import time p = subprocess.Popen(['...']) time.sleep(20) if p.poll() is None: p.kill() print 'timed out' else: print p.communicate()
它有一个缺点,你必须等待至少20秒才能完成。
import subprocess, threading class Command(object): def __init__(self, cmd): self.cmd = cmd self.process = None def run(self, timeout): def target(): print 'Thread started' self.process = subprocess.Popen(self.cmd, shell=True) self.process.communicate() print 'Thread finished' thread = threading.Thread(target=target) thread.start() thread.join(timeout) if thread.is_alive(): print 'Terminating process' self.process.terminate() thread.join() print self.process.returncode command = Command("echo 'Process started'; sleep 2; echo 'Process finished'") command.run(timeout=3) command.run(timeout=1)
其输出应为:
Thread started Process started Process finished Thread finished 0 Thread started Process started Terminating process Thread finished -15
可以看到,在第一次执行中,进程正确完成(返回代码0),而在第二次执行中,进程被终止(返回代码-15)。
我没有在windows中进行过测试;但是,除了更新示例命令之外,我认为它应该可以工作,因为我在文档中没有发现任何说明thread.join或process.terminate不受支持的内容。
我建议查看线程模块中的Timer class。我用它来实现Popen的超时。
首先,创建回调:
def timeout( p ): if p.poll() is None: print 'Error: process taking too long to complete--terminating' p.kill()
然后打开进程:
proc = Popen( ... )
然后创建一个计时器,调用将进程传递给它的回调。
t = threading.Timer( 10.0, timeout, [proc] ) t.start() t.join()
在程序的稍后部分,您可能需要添加行:
t.cancel()
否则,python程序将一直运行,直到计时器完成运行为止。
编辑:有人告诉我,在p.poll()和p.kill()调用之间存在子进程p可能终止的竞争条件。我相信下面的代码可以解决这个问题:
import errno def timeout( p ): if p.poll() is None: try: p.kill() print 'Error: process taking too long to complete--terminating' except OSError as e: if e.errno != errno.ESRCH: raise
尽管您可能希望清除异常处理,以便仅处理子流程已正常终止时发生的特定异常。
subprocess.Popen不阻塞,因此您可以执行以下操作:
它有一个缺点,你必须等待至少20秒才能完成。
其输出应为:
可以看到,在第一次执行中,进程正确完成(返回代码0),而在第二次执行中,进程被终止(返回代码-15)。
我没有在windows中进行过测试;但是,除了更新示例命令之外,我认为它应该可以工作,因为我在文档中没有发现任何说明thread.join或process.terminate不受支持的内容。
我建议查看线程模块中的Timer class。我用它来实现Popen的超时。
首先,创建回调:
然后打开进程:
然后创建一个计时器,调用将进程传递给它的回调。
在程序的稍后部分,您可能需要添加行:
否则,python程序将一直运行,直到计时器完成运行为止。
编辑:有人告诉我,在p.poll()和p.kill()调用之间存在子进程p可能终止的竞争条件。我相信下面的代码可以解决这个问题:
尽管您可能希望清除异常处理,以便仅处理子流程已正常终止时发生的特定异常。
相关问题 更多 >
编程相关推荐