休息功能,并在一段时间后过去 - Python
我一直在试图创建一个超时,告诉我的代码的一部分,如果它在一定的时间内没有达到结果,继续前进。休息功能,并在一段时间后过去 - Python
我测试了从这里发布的主要答案中的代码:break the function after certain time,它的工作原理非常完美,但是当我使用我的代码实现它时无法正常工作。
无论“Try”内的代码块执行多长时间,TimeoutException都不会被触发。代码块内的计时器始终以大于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的禅宗中也如此)。
如果您有权访问该函数源代码,寻找try/excecpt块并包含打印件以检查它,并捕获特定的异常,而不是裸露的除外。
如果不能深入到代码 - 你可以做一个单杆试图改变你TimeoutException
到BaseException
的底座(代替Exception
)。
在任何情况下,您似乎都不是解决手头问题的最佳方法 - 信号与许多类型的代码很不协调,包括多线程或其他事件循环基于代码。此外,即使您的处理程序在适当的时候正确地引发了Python异常,但如果您的长时间运行的函数是本机代码,那么Python本身不会处理该异常(并因此将执行切换到except
块),直到本机代码函数返回。我认为这是你的(唯一)问题,因为在这种情况下,下面的打印语句不会运行 - 这将花费超过5秒钟,并且它们执行except
块。
真正的解决
你可能想尝试使用Python的concurrent.future模块来运行你的长期功能。通过这种方式,你可以在另一个线程中运行你的长期功能,或多或少透明的方式(甚至在另一个进程中,这将利用多个内核),并为执行指定一个超时参数--Python的并发。未来的机器将自行处理停止计算。
此示例适用于交互式解释,并提出了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)