嵌套子流程未停止

时间:2018-10-24 17:43:23

标签: python subprocess

我有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

实际上,为了更加准确,我立即获得了前三行打印机,然后在2.5秒后获得了第四行打印,并得到了bash提示,然后在7.5秒后end sleeper出现在我的bash提示中。 >

我如何做到这样,通过超时杀死子进程也会杀死由该子进程运行的子进程?

1 个答案:

答案 0 :(得分: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.5s。

参考文献: