我有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提示中。 >
我如何做到这样,通过超时杀死子进程也会杀死由该子进程运行的子进程?
答案 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。
参考文献: