一个接一个地杀死Python子进程的子进程.超时已过期引发



我在Python中调用一个shell脚本fom,它会产生多个子进程。我想终止该进程及其所有子进程,如果它在两分钟后未完成。

有什么方法可以使用subprocess.run做到这一点,还是必须回到使用Popen?由于运行是阻塞的,我无法将 pid 保存在某个地方以在额外的命令中杀死孩子。一个简短的代码示例:

try:
subprocess.run(["my_shell_script"], stderr=subprocess.STDOUT, timeout=120)
except subprocess.TimeoutExpired:                                                                      
print("Timeout during execution")

这个问题被报告为一个错误给Python开发人员。它似乎特别发生在 stderr 或 stdout 被重定向时。 这是@Tanu代码的更正确版本。

import subprocess as sp
try:
proc = sp.Popen(['ls', '-l'], stdout=sp.PIPE, stderr=sp.PIPE)
outs, errs = proc.communicate(timeout=120)
except sp.TimeoutExpired:
proc.terminate()

Popen 不接受timeout作为参数。它必须传递给communicate. 在 Posix 操作系统上,terminatekill更温和,因为它降低了创建僵尸进程的风险。

引用文档:

subprocess.run- 默认情况下,这不会捕获 stdout 或 stderr。为此,请为 stdout 和/或 stderr 参数传递 PIPE。

如果您不想使用 Popen((。模块中的其他函数,例如 .call((, .Popen((。

有三个"文件"流:用于输入的 stdin 和 stdout 和 stderr。应用程序决定在哪里写什么;通常错误和诊断信息给STDERR,其余的给Stdout。若要捕获其中任一输出的输出,请指定子进程。PIPE 参数,以便将"流"重定向到您的程序中。

要在超时后终止子进程,请执行以下操作:

import os
import signal
import subprocess
try:
proc = subprocess.Popen(["ls", "-l"], stdout=PIPE, stderr=PIPE, timeout=120)
except subprocess.TimeoutExpired:
os.kill(proc.pid, signal.SIGTERM)

相关内容

最新更新