有人可以帮我理解超时参数在子进程模块中是如何工作的,以及如何正确使用subprocess.TimeoutExpired异常?
我的用例是我有一个主流程序,它运行子进程作为其重复例程的一部分。众所周知,子进程会不时挂起。我想防止这种情况持续下去。
我原以为我可以使用timeout参数给孩子这么长的时间来运行。但是,在我的示例程序中,行为不符合我的预期。运行parent.py时,它会启动child.py,我可以看到child.py的输出计数。 4s之后,parent.py确实得到了subprocess.TimeoutExpired异常,但是child.py的输出仍然存在。这让我相信child.py进程实际上并没有被杀死。文档似乎暗示它会被杀死:
timeout参数传递给Popen.wait()。如果超时到期,子进程将被终止,然后再次等待。子进程终止后,将重新引发TimeoutExpired异常。
那么我怎么能解决这个问题呢?当我收到超时异常时,我是否需要以某种方式杀死我的子进程?
感谢您的帮助。
parent.py
#!/usr/bin/env python3
import os
import sys
import subprocess
p = subprocess.Popen("/path/to/python3 /path/to/child.py", shell=True)
try:
p.wait(timeout=4)
except subprocess.TimeoutExpired:
print("we got a timeout. exiting")
sys.exit(1)
child.py
#!/usr/bin/env python3
import os
import sys
import time
for i in range(200):
print("i is {}".format(i))
time.sleep(1)
答案 0 :(得分:2)
看起来你需要添加一个电话
p.terminate()
在您的父流程sys.exit
之前 - 根据https://docs.python.org/3/library/subprocess.html#subprocess.Popen的当前文档,您引用的位仅适用于subprocess.call
,而不你在这里使用。
答案 1 :(得分:1)
取自文件:
If the process does not terminate after timeout seconds, raise a TimeoutExpired exception. It is safe to catch this exception and retry the wait.
这意味着您可以捕获异常,除非您终止进程(或python),否则进程将继续执行。在你的情况下,因为你正在做
sys.exit(1)
然后python本身将被终止,Popen对象将被垃圾收集。