子进程超时失败
我想在子流程上使用超时
from subprocess32 import check_output
output = check_output("sleep 30", shell=True, timeout=1)
不幸的是,尽管这会引起超时错误,但它会在30秒后发生。看来check_output无法中断shell命令。
我该如何在Python方面阻止这种情况?我怀疑subprocess32无法杀死超时的进程。
-
with Popen(*popenargs, stdout=PIPE, **kwargs) as process: try: output, unused_err = process.communicate(inputdata, timeout=timeout) except TimeoutExpired: process.kill() output, unused_err = process.communicate() raise TimeoutExpired(process.args, timeout, output=output)
有两个问题:
- [第二个]
.communicate()
可能会等待后代进程,而不仅是直接子进程,请参见Python子进程.check_call与.check_output process.kill()
可能不会杀死整个进程树,请参阅如何终止用shell = True启动的python子进程
它导致您观察到的行为:
TimeoutExpired
一秒钟发生,shell被杀死,但check_output()
仅在孙sleep
进程退出后30秒内返回。要变通解决此问题,请杀死整个进程树(属于同一组的所有子进程):
#!/usr/bin/env python3 import os import signal from subprocess import Popen, PIPE, TimeoutExpired from time import monotonic as timer start = timer() with Popen('sleep 30', shell=True, stdout=PIPE, preexec_fn=os.setsid) as process: try: output = process.communicate(timeout=1)[0] except TimeoutExpired: os.killpg(process.pid, signal.SIGINT) # send signal to the process group output = process.communicate()[0] print('Elapsed seconds: {:.2f}'.format(timer() - start))
输出量
Elapsed seconds: 1.00
- [第二个]