Python:超时异常处理 Signal.Alarm
Python: Timeout Exception Handling with Signal.Alarm
如果函数调用时间过长,我正在尝试实现超时异常处理程序。
编辑:事实上,我正在使用子进程编写一个Python脚本,它调用带有参数的旧C++程序。我知道该程序有时会挂起,不返回任何内容。这就是为什么我试图设定一个时间限制并继续使用不同参数等进行下一次调用的原因。
我一直在寻找并尝试实现它,但它不太奏效,所以我希望得到一些帮助。我目前拥有的是:
#! /usr/bin/env python
import signal
class TimeOutException(Exception):
def __init__(self, message, errors):
super(TimeOutException, self).__init__(message)
self.errors = errors
def signal_handler(signum, frame):
raise TimeOutException("Timeout!")
signal.signal(signal.SIGALRM, signal_handler)
signal.alarm(3)
try:
while True:
pass
except TimeOutException:
print "Timed out!"
signal.alarm(0)
编辑:我目前收到的错误消息是“TypeError:init() 正好需要 3 个参数(给定 2 个)
另外,我想问一个关于 except 块的基本问题。 "except TimeOutException" 正下方的代码与 "Exception handler" 中的代码有什么作用区别?似乎两者都可以做同样的事情?
如有任何帮助,我们将不胜感激。
if a function call is taking too long
我意识到这对于没有经验的开发人员来说可能不是很明显,但是适用于解决这个问题的方法完全取决于您在这个 "busy function" 中所做的事情,例如:
计算量大吗?如果是,您使用的是哪个 Python 解释器? CPython 还是 PyPy?如果 CPython: 这个计算只使用 Python 字节码还是涉及外包给编译机器代码的函数调用(它可能持有 Python 的全局解释器锁以获得相当多的无法控制的数量时间)?
这是很多 I/O 的工作吗?如果是,你能在任意状态下中止这个 I/O 工作吗?还是需要适当清理?您使用的是某种框架,例如 gevent 或 Twisted?
编辑:
所以,看起来你只是在生成一个子进程并等待它终止。太好了,这实际上是实现超时控制的最简单的问题之一。 Python (3) 附带相应功能! :-) 看看
https://docs.python.org/3/library/subprocess.html#subprocess.call
The timeout argument is passed to Popen.wait(). If the timeout
expires, the child process will be killed and then waited for again.
The TimeoutExpired exception will be re-raised after the child process
has terminated.
编辑2:
给你的示例代码,将其保存到文件中并使用 Python 3.3 执行它,至少:
import subprocess
try:
subprocess.call(['python', '-c', 'print("hello")'], timeout=2)
except subprocess.TimeoutExpired as e:
print("%s was terminated as of timeout. Its output was:\n%s" % (e.cmd, e.output))
try:
subprocess.call(['python'], timeout=2)
except subprocess.TimeoutExpired as e:
print("%s was terminated as of timeout. Its output was:\n%s" % (e.cmd, e.output))
在第一种情况下,子进程立即returns。不会引发超时异常。在第二种情况下,超时到期,您的控制进程(进程 运行 上面的脚本)将尝试终止子进程。这成功了。之后,引发 subprocess.TimeoutExpired
并由异常处理程序处理。对我来说,上面脚本的输出是 ['python'] was terminated as of timeout. Its output was:
None
:
如果函数调用时间过长,我正在尝试实现超时异常处理程序。
编辑:事实上,我正在使用子进程编写一个Python脚本,它调用带有参数的旧C++程序。我知道该程序有时会挂起,不返回任何内容。这就是为什么我试图设定一个时间限制并继续使用不同参数等进行下一次调用的原因。
我一直在寻找并尝试实现它,但它不太奏效,所以我希望得到一些帮助。我目前拥有的是:
#! /usr/bin/env python
import signal
class TimeOutException(Exception):
def __init__(self, message, errors):
super(TimeOutException, self).__init__(message)
self.errors = errors
def signal_handler(signum, frame):
raise TimeOutException("Timeout!")
signal.signal(signal.SIGALRM, signal_handler)
signal.alarm(3)
try:
while True:
pass
except TimeOutException:
print "Timed out!"
signal.alarm(0)
编辑:我目前收到的错误消息是“TypeError:init() 正好需要 3 个参数(给定 2 个)
另外,我想问一个关于 except 块的基本问题。 "except TimeOutException" 正下方的代码与 "Exception handler" 中的代码有什么作用区别?似乎两者都可以做同样的事情?
如有任何帮助,我们将不胜感激。
if a function call is taking too long
我意识到这对于没有经验的开发人员来说可能不是很明显,但是适用于解决这个问题的方法完全取决于您在这个 "busy function" 中所做的事情,例如:
计算量大吗?如果是,您使用的是哪个 Python 解释器? CPython 还是 PyPy?如果 CPython: 这个计算只使用 Python 字节码还是涉及外包给编译机器代码的函数调用(它可能持有 Python 的全局解释器锁以获得相当多的无法控制的数量时间)?
这是很多 I/O 的工作吗?如果是,你能在任意状态下中止这个 I/O 工作吗?还是需要适当清理?您使用的是某种框架,例如 gevent 或 Twisted?
编辑: 所以,看起来你只是在生成一个子进程并等待它终止。太好了,这实际上是实现超时控制的最简单的问题之一。 Python (3) 附带相应功能! :-) 看看
https://docs.python.org/3/library/subprocess.html#subprocess.call
The timeout argument is passed to Popen.wait(). If the timeout expires, the child process will be killed and then waited for again. The TimeoutExpired exception will be re-raised after the child process has terminated.
编辑2:
给你的示例代码,将其保存到文件中并使用 Python 3.3 执行它,至少:
import subprocess
try:
subprocess.call(['python', '-c', 'print("hello")'], timeout=2)
except subprocess.TimeoutExpired as e:
print("%s was terminated as of timeout. Its output was:\n%s" % (e.cmd, e.output))
try:
subprocess.call(['python'], timeout=2)
except subprocess.TimeoutExpired as e:
print("%s was terminated as of timeout. Its output was:\n%s" % (e.cmd, e.output))
在第一种情况下,子进程立即returns。不会引发超时异常。在第二种情况下,超时到期,您的控制进程(进程 运行 上面的脚本)将尝试终止子进程。这成功了。之后,引发 subprocess.TimeoutExpired
并由异常处理程序处理。对我来说,上面脚本的输出是 ['python'] was terminated as of timeout. Its output was:
None
: