【问题标题】:Python: Timeout Exception Handling with Signal.AlarmPython:使用 Signal.Alarm 处理超时异常
【发布时间】:2015-02-06 19:58:37
【问题描述】:

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

编辑:事实上,我正在使用 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)

EDIT:我目前收到的错误消息是“TypeError: init() 只需要 3 个参数(给定 2 个)

另外,我想问一个关于 except 块的基本问题。 “除了 TimeOutException”下面的代码和“异常处理程序”中的代码之间的角色区别是什么?似乎两者都可以做同样的事情?

任何帮助将不胜感激。

【问题讨论】:

  • 你说“它不太行”。你能更具体一点吗?您是否遇到意外错误?您没有收到任何错误(包括预期的错误)吗?还有什么?
  • 已更新我的答案。
  • 显然,我无法将subprocess.callstdout=PIPE 一起使用,这是我需要的:s

标签: python exception-handling


【解决方案1】:

如果函数调用耗时过长

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

  • 这是一个繁重的计算吗?如果是,您使用的是哪个 Python 解释器? CPython 还是 PyPy?如果 CPython:此计算是否仅使用 Python 字节码,还是涉及外包给已编译机器代码的函数调用(可能会在相当长的时间内保持 Python 的全局解释器锁)?

  • I/O 工作量很大吗?如果是,你能在任意状态中止这个 I/O 工作吗?还是需要适当清理?您是否使用了某个框架,例如 gevent 或 Twisted?

编辑: 因此,看起来您只是在生成一个子进程并等待它终止。太好了,这实际上是实现超时控制的最简单的问题之一。 Python (3) 提供了相应的功能! :-) 看看

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

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

编辑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))

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

【讨论】:

  • 实际上,我正在做的是调用另一个 C++ 程序,它又老又臭,我使用 Python 作为脚本语言。我将编辑问题。
  • 那么,您使用的是子进程吗? subprocess 提供了一个 Timeout 控件。
  • 哦,所以它可能就像将我的 subprocess.Popen 命令替换为 subprocess.call 并添加了计时器参数一样简单?
  • 对,你需要用subprocess.TimeoutExpired 捕手包裹你的call()
  • 可悲的是,我不认为我可以使用它...我在旧机器上使用 Python 2.6,而 subprocess.TimeoutExpired 在 Python 3.3 上是新的,我认为:s ...或者也许我做错了什么......悲伤的脸*
猜你喜欢
  • 2017-01-24
  • 2016-04-25
  • 1970-01-01
  • 1970-01-01
  • 2011-02-17
  • 2015-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多