中断功能并在一定时间后继续 - Python

Break function and move on after certain time has elapsed - Python

我一直在尝试创建一个超时,告诉我的一段代码在一定时间内没有达到结果时继续前进。

我测试了此处发布的主要答案中的代码:break the function after certain time,它运行良好,但是当我用我的代码实现它时它不起作用。

无论 'Try' 中的代码块执行多长时间,都不会触发 TimeoutException。此代码块中的计时器始终打印出大于 5 秒,即使如果代码花费的时间超过 signal.alarm(5).signal.alarm(5).

允许的 5 秒,甚至不应调用打印操作。

您能想到没有触发 TimeoutException 的任何原因吗?我该如何解决?

import signal
import time

def evaluateList(dataDictionaryList):
    newDataDict = []
    count = 0


    class TimeoutException(Exception):   
        pass

    def timeout_handler(signum, frame):   
        raise TimeoutException

    signal.signal(signal.SIGALRM, timeout_handler)


    for dataDictionary in dataDictionaryList:

        signal.alarm(5)

        try:
            startTime = time.time()
            newDataDict.append(functionThatMightHang(dataDictionary))
            print(count + 1, '  Time to evaluate: ', time.time() - startTime)
            count+=1

        except TimeoutException:
            print('took too long')
            continue
        else:
            signal.alarm(0)

    return newDataDict

它确实应该工作——除非 functionThatMightHang 中的某些代码块本身捕获并吞噬了您的 TimeoutException。如果有一个 try/except 块在其中捕获一个空 Exception 并且只是忽略它并继续计算,就会发生这种情况。 (这是一种糟糕的编程习惯,甚至在 Python 的 zen 中也被列为如此)。

如果您有权访问该函数的源代码,请寻找 try/excecpt 块并包括打印以检查它,并捕获特定的异常而不是裸露的异常。

如果您无法深入研究该代码 - 您可以一次性尝试将 TimeoutException 的基数更改为 BaseException(代替 Exception)。

在任何情况下,您的方法似乎都不是解决手头问题的最佳方法 - 信号确实不能与很多类型的代码一起使用,包括多线程或其他事件 -基于循环的代码。

此外,即使您的处理程序在正确的时间正确地引发了 Python 异常,如果您的 long-运行ning 函数是本机代码,Python 本身也不会处理异常(并因此将执行切换到 except 块)直到本机代码函数 returns。我排除了这是你的(唯一)问题,因为在那种情况下,以下打印语句不会 运行 - 它会花费超过 5 秒,并且它们会执行 except 块。

真正修复

您可能想通过使用 Python 的 concurrent.future 模块来尝试 运行 您的长期功能。通过这种方式,您可以 运行 在另一个线程中以或多或少透明的方式(或者甚至在另一个进程中,这将利用多个内核)执行您的长期函数,并为执行指定超时参数- Python 的 concurrent.future 机器将自行处理停止计算。

此示例适用于交互式解释器,并引发 TimeoutError(concurrent.futures 使用的那个,不是自定义的):

from concurrent.futures import ThreadPoolExecutor
import time

def long():
    time.sleep(3)

p = ThreadPoolExecutor(1)

f = p.submit(long); f.result(timeout=1)