使用超时的子进程:在TimeoutExpired异常后应该怎么处理?
使用超时的子进程:在TimeoutExpired异常后应该怎么处理?
如果我按照Python文档的建议使用subprocess超时=秒,它对我无效:
# 可复制粘贴的代码片段 :-) import subprocess32 as subprocess import datetime now=datetime.datetime.now() pipe=subprocess.Popen('sleep 5', shell=True, stdout=subprocess.PIPE) try: pipe.communicate(timeout=1) except subprocess.TimeoutExpired, exc: time_delta=datetime.datetime.now()-now print(time_delta) assert time_delta
文档建议在TimeoutExpired后使用pipe.kill()和pipe.communicate():https://docs.python.org/3/library/subprocess.html#subprocess.Popen.communicate
对我来说不起作用。第二个
communicate()
没有立即返回。异常:
0:00:01.001234 0:00:05.002919 Traceback (most recent call last): File "/home/foo/src/test_timeout.py", line 16, inassert time_delta
如果我使用
['sleep', '5']
而不是shell=True
,它就可以正常工作。如果我不提供
stdout=subprocess.PIPE
,它也可以正常工作。我猜shell不会对pipe.kill()做出反应。
解决此问题的最佳方法是什么?
问题的出现的原因是在使用subprocess
模块进行子进程管理时,如果设置了超时时间,当子进程超时后会抛出TimeoutExpired
异常。在处理这个异常时,一般的做法是捕获TimeoutExpired
异常,然后终止已经启动的进程,再次调用.communicate()
方法。
然而,问题在于代码中的pipe.kill()
只会终止shell进程,而像/bin/sleep
这样的子进程可能会继续运行。要解决这个问题,可以参考链接How to terminate a python subprocess launched with shell=True
中的方法,来终止所有相关的子进程。
需要注意的是,如果不需要等待孙子进程的结束,可以参考链接Python subprocess .check_call vs .check_output中的方法。
感谢提供的其他StackO问题的链接,我将我的问题标记为重复问题。