【问题标题】:Wait for timeout or event being set for asyncio.Event等待为 asyncio.Event 设置超时或事件
【发布时间】:2018-04-03 05:35:15
【问题描述】:

我有一个类,其方法如下所示:

# self.stop_event -> threading.Event
def run(self):
    while not self.stop_event.wait(3):  # i.e. repeat every 3 sec
        pass  # do stuff

想法是其中几个在它们自己的线程中运行,并且在某些时候一个线程执行stop_event.set(),这自然会停止所有其他线程。我想为此切换到 asyncio,因为run 中的任务主要是在睡觉和做 IO。因此,我必须:

# self.stop_event -> asyncio.Event
async def run(self):
    while not self.stop_event.is_set():
        await asyncio.sleep(3)
        pass  # do stuff

问题是asyncio.Event是不能等待的,所以设置的时候,在方法完成之前最多有3秒的等待时间。这是一个问题,因为睡眠时间可能是几分钟。目前,我正在通过将run 包装在asyncio.Task 中,然后像event_loop.call_soon(the_task.cancel) 一样取消它来解决这个问题。

我想问是否有更好的方法来实现上述?有没有办法让asyncio.Event 以某种方式超时,类似于threading.Event

【问题讨论】:

  • IIRC,你可以很容易地为 asyncio 构建类似 Curio 的 timeout_after 函数,但它最终会变得有点重(因为你必须将它包裹在 Future 然后 @ 987654334@ 超时)。无论如何,有了它,你可以做await timeout_after(3, self.stop_event.wait),它得到你想要的。如果您有兴趣并且无法从该提示中弄清楚,我可以尝试挖掘我的实现,但可能要到明天......
  • 我找到了来源,会检查一下,谢谢。

标签: python events python-asyncio


【解决方案1】:

有没有一种方法可以让我以某种方式等待asyncio.Event 超时,类似于threading.Event

asyncio.wait_for 支持方便地向任何等待的协程添加超时。 asyncio.Eventthreading.Event.wait 超时功能的模拟可能如下所示:

async def event_wait(evt, timeout):
    # suppress TimeoutError because we'll return False in case of timeout
    with contextlib.suppress(asyncio.TimeoutError):
        await asyncio.wait_for(evt.wait(), timeout)
    return evt.is_set()

这允许run 与使用threading.Event 的几乎完全相同:

async def run(self):
    while not await event_wait(self.stop_event, 3):
        pass  # do stuff

【讨论】:

  • @IvanKalchev 谢谢。我考虑创建一个 Python 拉取请求,将可选超时添加到asyncio.Event.wait,但后来我注意到超时是intentionally left out,文档明确指向asyncio.wait_for。所以这个答案几乎就是它打算完成的方式。
  • 你知道为什么要使用单独的方法吗?
  • @IvanKalchev 我认为这个想法是那些 timeout 参数在 asyncio 中根本不需要 need 因为你可以使用 @987654334 @ 或 future.cancel,等等。线程不是这种情况,实际上需要超时参数,因为不支持中断线程(有充分的理由,不仅在 Python 中)。由于 asyncio 是关于阻塞调用和等待,几乎每个协程都必须支持 timeout 参数,因此开发人员决定省略所有这些参数并提供一个通用的asyncio.wait_for
  • @IvanKalchev 我认为在EventCondition 等的情况下这是一个糟糕的决定,否则它们被编写为与threading 对应物紧密建模,但值得,这个决定是故意的,这不仅仅是一个疏忽。对此事足够感兴趣的人应该在错误跟踪器上争论 timeout 参数是为Event.wait 和其他拥有它们的人实现的。
  • 感谢您的信息!我确信这不是疏忽,我只是想知道为什么会做出这个决定。
猜你喜欢
  • 2017-02-10
  • 2016-05-27
  • 1970-01-01
  • 2018-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多