Python:使用Signal.Alarm进行超时异常处理

时间:2015-02-06 19:58:38

标签: python exception-handling

如果函数调用时间太长,我正在尝试实现超时异常处理程序。

编辑:事实上,我正在使用subprocess编写一个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块的基本问题。 “TimeOutException除外”下的代码与“异常处理程序”中的代码之间的角色差异是什么?似乎两者都可以做同样的事情吗?

任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:3)

  

如果函数调用时间过长

我意识到这对于没有经验的开发人员来说可能并不明显,但适用于解决这个问题的方法完全取决于你在这个“忙碌功能”中所做的事情,例如:

  • 这是一个沉重的计算吗?如果是,您使用的是哪个Python解释器? CPython还是PyPy?如果CPython:这个计算只使用Python字节码,还是涉及函数调用外包给编译的机器代码(这可能会让Python的全局解释器锁保持相当无法控制的时间)?

  • 这是否有很多I / O工作?如果是,您可以在任意状态下中止此I / O工作吗?或者你需要妥善清理?您使用的是某个框架,例如gevent或Twisted吗?

修改 所以,它看起来你只是产生一个子进程并等待它终止。太棒了,这实际上是实现超时控制的最简单问题之一。 Python(3)提供了相应的功能! :-)看看

https://docs.python.org/3/library/subprocess.html#subprocess.call

  

timeout参数传递给Popen.wait()。如果超时   到期后,子进程将被杀死,然后再等待。   子进程后将重新引发TimeoutExpired异常   已经终止。

EDIT2:

示例代码,将其保存到文件并使用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))

在第一种情况下,子进程立即返回。不会引发超时异常。在第二种情况下,超时到期,您的控制进程(在上面的脚本上运行的进程)将尝试终止子进程。这成功了。之后,subprocess.TimeoutExpired被引发,异常处理程序处理它。对我来说,上面脚本的输出是['python'] was terminated as of timeout. Its output was: None