python - 在上下文管理器中捕获 threading.Timer 抛出的异常

标签 python multithreading timer exception contextmanager

我写了一个简单的 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

关于python - 在上下文管理器中捕获 threading.Timer 抛出的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29258146/

相关文章:

python - 在一种方法中创建的属性在另一种方法中不存在

javascript - setTimeout() 方法中的 clearTimeout() 在 JS 中不起作用

python - Python字典中的整型键是否按优先级排序和排序?

python - 如何使用sql读取csv

python - 将 dict 转换为具有不同命名空间的 xml

ios - 如何让按钮只在有限的时间内出现?

ios - 定时器未同步

multithreading - MSMQ中需要互斥体吗?

java - 内联 Thread 对象的运行速度比从 Thread 继承的类快得多

multithreading - MaxMind 的 GeoIP C 实现线程安全吗?