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

Understanding subprocess.TimeoutExpired, want to kill a child process after a timeout occurs

有人可以帮助我了解超时参数在子流程模块中的工作原理,以及如何正确使用 subprocess.TimeoutExpired 异常吗?

我的用例是我有一个主 运行ner 程序,它 运行 是一个 child 进程,作为其重复例程的一部分。 child 进程有时会挂起。我想防止这个挂起阻碍一切。

我在想我可以使用超时参数给 child 这么长的时间给 运行。但是,在我下面的示例程序中,行为并不是我所期望的。当 parent.py 为 运行 时,它会启动 child.py 并且我可以看到 child.py 的输出正在计数。 4 秒后 parent.py 确实得到 subprocess.TimeoutExpired 异常,但是 child.py 的输出不断出现。这让我相信 child.py 进程实际上并没有被杀死。文档似乎暗示它将被杀死:

The timeout argument is passed to Popen.wait(). If the timeout expires, the child process will be killed and then waited for again. The TimeoutExpired exception will be re-raised after the child process has terminated.

那么我该如何解决这个问题呢?当我收到超时异常时,我是否需要以某种方式自行终止我的 child 进程?

感谢您的帮助。

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)

看来您确实需要添加一个调用:

p.terminate()

在你的父进程中的sys.exit之前根据当前documentation你引用的位只适用于subprocess.call,那就是 你在这里用的是什么

摘自文档:

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