【发布时间】:2022-11-23 04:34:46
【问题描述】:
我正在使用以下代码启动子进程:
# Run the program
subprocess_result = subprocess.run(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
check=False,
timeout=timeout,
cwd=directory,
env=env,
preexec_fn=set_memory_limits,
)
启动的子进程也是一个 Python 程序,带有一个 shebang。
此子进程可能持续时间超过指定的timeout。
子进程进行大量计算并将结果写入文件,并且不包含任何信号处理程序。
根据文档https://docs.python.org/3/library/subprocess.html#subprocess.run,subprocess.run 杀死超时的孩子:
超时参数传递给 Popen.communicate()。如果超时 过期,子进程将被杀死并等待。这 TimeoutExpired 异常将在子进程完成后重新引发 终止。
当我的子进程超时时,我总是收到
subprocess.TimeoutExpired异常,但有时子进程没有被杀死,因此仍在消耗我机器上的资源。所以我的问题是,我在这里做错了什么吗?如果是,是什么,如果不是,为什么我会遇到这个问题,我该如何解决?
注意:我在 Ubuntu 22_04 上使用 Python 3.10
【问题讨论】:
-
@S.B 我的脚本做了一些繁重的计算并将结果写入文件,没有任何信号处理程序。不,不幸的是我无法确定脚本在超时后仍在运行的情况。您的评论是否表明我对文档的理解是正确的,因此理论上应该终止子进程?
-
什么可以正在发生的是您的子进程实际上正在产生一个单独的进程来执行计算。
subprocess.run会杀了孩子,但孙辈会由1继承。如果没有看到您正在运行的实际进程,这是不可能诊断的,但是鉴于您所说的(这些是“繁重的计算”),多处理似乎已经到位。 -
解决这个问题的方法是修改您的子进程以接受信号以执行适当的清理,或者编写一个包装脚本来简单地接收信号,杀死它的所有后代,然后死去
-
谢谢你的 cmets @Bakuriu 我会从那边看,但事实是子进程不是我的 :) 而且我认为即使他们不再启动子进程,其中一些也不会被杀死,但我需要检查那个。
-
@ManuelSelva 好的。查看
subprocess.run的源代码,它使用.kill()method on timeout 和 sendsSIGKILL和 cannot be handled。所以我相信在你的情况下你真的不能做太多。不要使用timeout并以其他方式实现超时
标签: python subprocess kill-process