功能超时

时间:2013-08-29 20:53:32

标签: python python-2.7 time infinite-loop

我们假设我们有一个python函数magical_attack(energy),它可能持续或不持续超过一秒。它甚至可能是一个无限循环?我将如何运行,但如果超过一秒,则终止它,然后告诉程序的其余部分。我正在寻找一个光滑的模块来做到这一点。例如:

import timeout
try: timout.run(magical_attack(5), 1)
except timeout.timeouterror:
    blow_up_in_face(wizard)

注意:修改功能是不可能的。它来自运行时的外部。

2 个答案:

答案 0 :(得分:1)

最简单的方法是运行后台代码in a thread

t = threading.Thread(target=magical_attack, args=(5,))
t.start()
t.join(1)
if not t.isAlive():
    blow_up_in_face(wizard)

但请注意,这不会取消 magical_attack功能;即使你不再关心结果,它仍然可以在后台继续旋转,只要它想要它。

安全地取消线程本质上很难做到,并且在每个平台上都有所不同,因此Python不会尝试提供这样做的方法。如果您需要,有三种选择:

  1. 如果你可以编辑magical_attack的代码来经常检查一个标志,你可以通过设置那个标志来合作取消它。
  2. 您可以使用a child process代替线程,然后可以安全地杀死。
  3. 您可以使用ctypespywin32PyObjC等来访问特定于平台的例程以终止线程。但是你必须真正知道你正在做什么来确保你安全地做到这一点,不要混淆Python做这件事。
  4. 正如Chris Pak所指出的,Python 3.2+中的futures模块使这更容易。例如,您可以在没有数千个线程的情况下丢弃数千个作业;您可以将超时应用于整组工作,就好像它们只是一份工作一样;此外,您可以通过简单的单线程更改从线程切换到进程。不幸的是,Python 2.7没有这个模块 - 但是有一个准官方backport可以轻松安装和使用。

答案 1 :(得分:0)

除了这个细节之外,Abamert在我准备的答案上打败了我:

当且仅当外部函数通过Python解释器执行时,即使您无法更改它(例如,从已编译的模块中),您也可以使用此其他问题中描述的技术使用异常终止调用该函数的线程。

Is there any way to kill a Thread in Python?

当然,如果您确实可以控制您正在调用的函数,那么该答案的StoppableThread类可以很好地解决这个问题:

import threading

class StoppableThread(threading.Thread):
    """Thread class with a stop() method. The thread itself has to check
    regularly for the stopped() condition."""

    def __init__(self):
        super(StoppableThread, self).__init__()
        self._stop = threading.Event()

    def stop(self):
        self._stop.set()

    def stopped(self):
        return self._stop.isSet()

class Magical_Attack(StoppableThread):
    def __init__(self, enval):
        self._energy = enval
        super(Magical_Attack, self).__init__()

    def run(self):
        while True and not self.stopped():
            print self._energy

if __name__ == "__main__":
    a = Magical_Attack(5)
    a.start()
    a.join(5.0)
    a.stop()