了解subprocess.TimeoutExpired,想要在发生超时后终止子进程

时间:2015-01-24 23:56:16

标签: python subprocess

有人可以帮我理解超时参数在子进程模块中是如何工作的,以及如何正确使用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)

2 个答案:

答案 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对象将被垃圾收集。