在上下文管理器中捕获 threading.Timer 抛出的异常
Catching exception thrown by threading.Timer in a context manager
我写了一个简单的 TimeManager
:上下文管理器在进入上下文时触发 threading.Timer
并在退出时取消它。如果计时器在退出上下文之前关闭,则会引发异常:
import threading
class TimeManager(object):
def __init__(self):
self._timeout = 1
def _timeoutHandler(self):
raise Exception("Timeout!")
def __enter__(self):
self.timer = threading.Timer(self._timeout, self._timeoutHandler)
self.timer.start()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.timer.cancel()
return False
显然我无法在主线程中捕获异常,因为它属于一个单独的线程:
>>> with TimeManager() as t:
... try:
... time.sleep(5)
... except Exception:
... print "caught"
...
Exception in thread Thread-3:
Traceback (most recent call last):
File "/usr/lib64/python2.6/threading.py", line 532, in __bootstrap_inner
self.run()
File "/usr/lib64/python2.6/threading.py", line 736, in run
self.function(*self.args, **self.kwargs)
File "<stdin>", line 5, in _timeoutHandler
Exception: Timeout!
那么,如何在主线程中捕获异常呢?
我应该放弃上下文管理器的想法吗?
请注意,该问题与描述的问题不同 here,那里不涉及多线程。
我认为它也不同于this,其中消息传递会否定超时的目的。
有一个名为 stopit
的模块使用线程或信号提供可中断的上下文管理器。但是,每种方法都有其自身的局限性。例如,使用线程,您实际上不能中断阻塞调用(如 time.sleep)。信号可以,但仅在 Unix 上可用,并且在多线程应用程序中使用不安全。
看起来它利用 C-API 函数 PyThreadState_SetAsyncExc
在所需线程中异步引发异常。
这是一个用法示例(取自他们的文档):
>>> import time
>>> def variable_duration_func(duration):
... t0 = time.time()
... while True:
... dummy = 0
... if time.time() - t0 > duration:
... break
>>>
>>> start_time = time.time()
>>> with Timeout(2.0) as timeout_ctx:
... variable_duration_func(5.0)
>>> time.time() - start_time < 2.2
True
>>> timeout_ctx.state == timeout_ctx.TIMED_OUT
True
我写了一个简单的 TimeManager
:上下文管理器在进入上下文时触发 threading.Timer
并在退出时取消它。如果计时器在退出上下文之前关闭,则会引发异常:
import threading
class TimeManager(object):
def __init__(self):
self._timeout = 1
def _timeoutHandler(self):
raise Exception("Timeout!")
def __enter__(self):
self.timer = threading.Timer(self._timeout, self._timeoutHandler)
self.timer.start()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.timer.cancel()
return False
显然我无法在主线程中捕获异常,因为它属于一个单独的线程:
>>> with TimeManager() as t:
... try:
... time.sleep(5)
... except Exception:
... print "caught"
...
Exception in thread Thread-3:
Traceback (most recent call last):
File "/usr/lib64/python2.6/threading.py", line 532, in __bootstrap_inner
self.run()
File "/usr/lib64/python2.6/threading.py", line 736, in run
self.function(*self.args, **self.kwargs)
File "<stdin>", line 5, in _timeoutHandler
Exception: Timeout!
那么,如何在主线程中捕获异常呢? 我应该放弃上下文管理器的想法吗?
请注意,该问题与描述的问题不同 here,那里不涉及多线程。 我认为它也不同于this,其中消息传递会否定超时的目的。
有一个名为 stopit
的模块使用线程或信号提供可中断的上下文管理器。但是,每种方法都有其自身的局限性。例如,使用线程,您实际上不能中断阻塞调用(如 time.sleep)。信号可以,但仅在 Unix 上可用,并且在多线程应用程序中使用不安全。
看起来它利用 C-API 函数 PyThreadState_SetAsyncExc
在所需线程中异步引发异常。
这是一个用法示例(取自他们的文档):
>>> import time
>>> def variable_duration_func(duration):
... t0 = time.time()
... while True:
... dummy = 0
... if time.time() - t0 > duration:
... break
>>>
>>> start_time = time.time()
>>> with Timeout(2.0) as timeout_ctx:
... variable_duration_func(5.0)
>>> time.time() - start_time < 2.2
True
>>> timeout_ctx.state == timeout_ctx.TIMED_OUT
True