子进程超时:TimeoutExpired 异常后怎么办? [复制]

Posted

技术标签:

【中文标题】子进程超时:TimeoutExpired 异常后怎么办? [复制]【英文标题】:subprocess with timeout: What to do after TimeoutExpired Exception? [duplicate] 【发布时间】:2016-08-04 04:12:35 【问题描述】:

如果我遵循 python 文档的建议,subprocess timeout=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')

在 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,那么它也可以。

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

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

【问题讨论】:

【参考方案1】:

一般模式:捕获TimeoutExpired,杀死启动的进程,再次调用.communicate()是正确的。

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

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

【讨论】:

感谢您提供指向其他 StackO 问题的链接。我将我的问题标记为重复。

以上是关于子进程超时:TimeoutExpired 异常后怎么办? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

Sitecore 8.1 重建链接数据库出现超时异常

处理 ClientInsertServerInsert 同步冲突时出现 SQL 命令“超时”异常

优化实体框架查询 - 超时已过期

MySql.Data.MySqlClient.MySqlException:超时已过期

超时已过。在 Azure sql 上完成操作之前经过的超时时间

System.Data.SqlClient.SqlException:超时已过期