【问题标题】:nested subprocess not stopping嵌套子进程没有停止
【发布时间】:2018-10-24 17:43:22
【问题描述】:

我有 3 个文件:

sleeper.py

import subprocess

print('start sleeper')
subprocess.run(['sleep', '10'])
print('end sleeper')

waker.py

import subprocess

print('The waker begins')
try:
    subprocess.run(['python3', 'sleeper.py'], timeout=5)
except subprocess.TimeoutExpired:
    pass
print('The waker ends')

awake.py

import subprocess

print('Awake begin')
try:
    subprocess.run(['python3', 'waker.py'], timeout=2.5)
except subprocess.TimeoutExpired:
    pass
print('Awake end')

然后我运行python3 awake.py

但得到以下输出:

Awake begin
The waker begins
start sleeper
Awake end
end sleeper

实际上更准确地说,我立即得到前 3 行打印机,然后 2.5 秒后打印第 4 行并得到我的 bash 提示符,然后 7.5 秒后 end sleeper 出现在我的 bash 提示符上。

如何使通过超时杀死子进程也会杀死该子进程运行的子进程?

【问题讨论】:

  • run 应该在超时到期时终止子进程。它也会终止孩子吗?在您的情况下似乎并非如此。一种解决方法是使用Popen,轮询超时,然后杀死进程和子进程,例如:*.com/a/27034438/6451573。这很hacky...

标签: python subprocess


【解决方案1】:

run 应该在超时到期时终止子进程。它也会终止孩子吗?在您的情况下似乎并非如此。一种解决方法是使用Popen,轮询超时,然后杀死进程和子进程。

似乎你不能同时拥有它:使用 run 并确保所有子进程都被终止(当你得到 TimeoutException 时,进程已经被杀死,所以你失去了孩子的踪迹)

proc = subprocess.Popen(args, stderr=errFile, stdout=outFile, universal_newlines=False)
wait_remaining_sec = 2.5

while proc.poll() is None and wait_remaining_sec > 0:
    time.sleep(0.5)
    wait_remaining_sec -= 0.5

if proc.poll() is None:
   # process is still there: terminate it and subprocesses:
   import psutil

   parent_pid = proc.pid  # we get the process pid
   parent = psutil.Process(parent_pid)
   for child in parent.children(recursive=True):
      child.kill()
   parent.kill()

轮询循环比简单的time.sleep(2.5) 调用要好,因为如果进程在超时之前结束,您不想等待 2.5 秒。如果进程在此之前结束,这不会导致超过 0.5 秒的延迟。

参考资料:

【讨论】:

  • while proc.poll() is None and wait_remaining_sec > 0: time.sleep(0.5) wait_remaining_sec -= 0.5 而不仅仅是time.sleep(2.5) 有什么原因吗?
  • 是的,因为如果进程在超时之前结束,您不想等待 2.5 秒。