中断函数并在经过一段时间后继续 - Python

时间:2017-05-28 05:19:14

标签: python timeout signals

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

我测试了这里发布的主要答案中的代码:break the function after certain time,它运行得很完美但是当我用我的代码实现它时它不起作用。

永远不会触发TimeoutException,无论“尝试”中的代码块需要多长时间。执行。即使在代码花费的时间超过signal.alarm(5)允许的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

1 个答案:

答案 0 :(得分:1)

它应该确实有效 - 除非functionThatMightHang内的某些代码块本身正在捕获并吞下你的TimeoutException。如果有一个try / except块在那里捕获一个裸Exception,只是忽略它并继续计算,就会发生这种情况。 (这是一个糟糕的编程习惯,甚至在Python的禅宗中列出)。

如果您可以访问该功能源代码,请搜索try / excecpt块并包含打印以检查它,并捕获特定的异常而不是裸除。

如果您无法深入了解该代码 - 您可以尝试单次尝试将TimeoutException的基础更改为BaseException(代替Exception)。

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

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

真正修复

您可能希望尝试使用Python的concurrent.future模块运行您的长期功能。通过这种方式,您可以在另一个线程中以一种或多或少透明的方式运行您的长期函数(或者甚至在另一个进程中,它将利用多个核心),并为执行指定一个超时参数 - Python&#39 ; 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)