带超时的子进程:TimeoutExpired异常后该怎么办?

时间:2016-04-13 07:58:05

标签: python shell timeout subprocess

子进程超时=如果我遵循python文档的建议,SECONDS对我不起作用:

# copy+pasteable snippet :-)
import subprocess32 as subprocess
import datetime

now=datetime.datetime.now()
pipe=subprocess.Popen('sleep 5', shell=True, stdout=subprocess.PIPE)
try:
    pipe.communicate(timeout=1)
except subprocess.TimeoutExpired, exc:
    time_delta=datetime.datetime.now()-now
    print(time_delta)
    assert time_delta<datetime.timedelta(seconds=3), time_delta
    pipe.kill()
    outs, errs = pipe.communicate()
    time_delta=datetime.datetime.now()-now
    print(time_delta)
    assert time_delta<datetime.timedelta(seconds=3), time_delta
    print('OK')

docout建议在TimeoutExpired之后使用pipe.kill()和pipe.communicate():https://docs.python.org/3/library/subprocess.html#subprocess.Popen.communicate

它对我不起作用。第二个communicate()不会很快返回。

例外:

0:00:01.001234
0:00:05.002919
Traceback (most recent call last):
  File "/home/foo/src/test_timeout.py", line 16, in <module>
    assert time_delta<datetime.timedelta(seconds=3), time_delta
AssertionError: 0:00:05.002919

如果我使用['sleep', '5']代替shell=True,那么它可以正常运行。 如果我不提供stdout=subprocess.PIPE,那么它也可以。

我猜shell不会对pipe.kill()做出反应。

解决这个问题的最佳方法是什么?

1 个答案:

答案 0 :(得分:1)

一般模式:catch TimeoutExpired,kill kill processes,再次调用.communicate()是正确的。

问题是代码中的pipe.kill()只会杀死shell,而/bin/sleep等后代进程可能会继续运行。请参阅How to terminate a python subprocess launched with shell=True

注意:如果需要;没有必要等待孙子进程。请参阅Python subprocess .check_call vs .check_output