Subprocess timeout failure
我想在子进程上使用超时
1 2 | from subprocess32 import check_output output = check_output("sleep 30", shell=True, timeout=1) |
不幸的是,虽然这会引发超时错误,但它会在30秒后发生。 似乎check_output不能中断shell命令。
我可以在Python端做些什么来阻止它?
我怀疑subprocess32无法终止超时进程。
超时的
1 2 3 4 5 6 7 | 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 vs
.check_output -
process.kill() 可能不会终止整个进程树,请参阅如何终止使用shell = True启动的python子进程
它会导致您观察到的行为:
要解决问题,请终止整个进程树(属于同一组的所有子进程):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #!/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)) |
产量
1 | Elapsed seconds: 1.00 |
Python 3.6的更新。
这仍然在发生,但我已经测试了很多
我的结论:在
注意:
如果你看看Python 3.6里面的代码,它基本上是用
因此,要解决Python 3.5或3.6上的@innisfree问题,请执行以下操作:
1 | check_output(['sleep', '30'], timeout=1) |
对于其他情况,请避免混合