我正在编写类似的程序
results = []
for i in range(30):
x = 4 ** 5 ** i
results.append(x)
但是,当i
变大(并且结果不会太大而不能筹集OverflowError
)时,将需要很长的时间来计算结果。因此,我想设置一个超时机制,如果计算时间超过1秒,该机制将continue
。
我尝试使用eventlet
这样的软件包
from eventlet import Timeout
with Timeout(1) as timeout:
x = 4 ** 5 ** 20
但是timeout
无法正常工作。 (也许只是因为我只执行一行代码。)我从StackOverflow发现的其他方法也失败了……
是否存在一种可能的编程方式来为此“简单但复杂”的计算设置超时?或者,还有其他方法吗? (例如,结果太大时退出...)
感谢您的帮助!
答案 0 :(得分:1)
首先,尝试为此使用eventlet
是错误的工具。 eventlet
主要用于使用以greenlets形式的协程进行非阻塞I / O。与CPU相关的问题无关(实际上,eventlet.Timeout
的文档已阅读):
如果try / finally或with块中的代码块从不协作产生,则无法提高超时时间。在Eventlet中,这应该很少有问题,但是请注意,使用此类不能使仅CPU的操作超时。
这意味着,如果您有一些执行CPU绑定操作的代码块,则您仍不会中断,因为该代码永远不会屈服于另一个线程。如果您可能需要一些代码来检查套接字上是否有要读取的数据,或者不产生数据,这种情况就更适用。
如果要在一段时间后设置中断以中断长时间运行的计算,则可以使用signal.alarm
并设置SIGALRM
处理程序。您可以将其全部包装在上下文管理器中,例如:
>>> import signal
>>> from contextlib import contextmanager
>>> class TimeoutError(RuntimeError): pass
...
>>> @contextmanager
... def timeout(seconds):
... def handler(*args):
... raise TimeoutError("timed out after {} seconds".format(seconds))
... orig_handler = signal.signal(signal.SIGALRM, handler)
... signal.alarm(seconds)
... try:
... yield
... finally:
... signal.alarm(0)
... signal.signal(signal.SIGALRM, orig_handler)
...
>>> with timeout(10):
... while True: pass
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "<stdin>", line 4, in handler
__main__.TimeoutError: timed out after 10 seconds
>>> with timeout(10):
... print(1 + 1)
...
2
>>> with timeout(10):
... 4 ** 5 ** 20
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "<stdin>", line 4, in handler
__main__.TimeoutError: timed out after 10 seconds
注意:,这仅适用于* NIX系统,尽管也可以在Windows上进行。