等待为asyncio.Event设置超时或事件

Iva*_*hev 4 python events python-asyncio

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

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

这个想法是,其中一些是在他们自己的线程中运行的,并且在某个时刻,一个线程会运行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
Run Code Online (Sandbox Code Playgroud)

问题是asyncio.Event无法等待,因此在设置时,在方法完成之前最多等待3秒钟.这是一个问题,因为睡眠时间可能是几分钟.目前,我正在解决这个问题,run包括一个asyncio.Task然后取消它event_loop.call_soon(the_task.cancel).

我想问一下是否有更好的方法来实现上述目标?有没有办法我可以在asyncio.Event某种程度上等待超时,类似于threading.Event

use*_*342 11

有没有办法我可以在asyncio.Event某种程度上等待超时,类似于threading.Event

asyncio.wait_for可以方便地为任何协同程序添加超时.threading.Event.wait使用超时的仿真可能如下所示:

async def event_wait(evt, timeout):
    try:
        await asyncio.wait_for(evt.wait(), timeout)
    except asyncio.TimeoutError:
        pass
    return evt.is_set()
Run Code Online (Sandbox Code Playgroud)

这允许run几乎完全像使用的那个threading.Event:

async def run(self):
    while not await event_wait(self.stop_event, 3):
        pass  # do stuff
Run Code Online (Sandbox Code Playgroud)

  • @IvanKalchev 谢谢。我考虑创建一个 Python 拉取请求,将可选超时添加到 `asyncio.Event.wait`,但后来我注意到超时是[故意省略](https://docs.python.org/3/library/asyncio -sync.html),文档明确指向“asyncio.wait_for”。所以这个答案几乎就是它想要完成的方式。 (3认同)
  • @IvanKalchev,我认为对于“Event”、“Condition”等来说,这是一个糟糕的决定,这些事件本来是为了紧密模拟其“线程”对应项而编写的,但就其价值而言,该决定是有意的,而不是只是一个疏忽。对此事足够感兴趣的人应该在错误跟踪器上争论,为“Event.wait”和其他拥有它们的人实现_timeout_参数。 (3认同)
  • @IvanKalchev我认为这个想法是,在 asyncio 中根本不需要这些 _timeout_ 参数,因为你可以只使用 `asyncio.wait_for` 或 `future.cancel` 等等。线程的情况并非如此,线程中超时参数实际上是必要的,因为不支持中断线程(有充分的理由,而且不仅在 Python 中)。由于 asyncio 是关于阻塞调用和等待的,所以几乎每个协程都必须支持 _timeout_ 参数,因此开发人员决定忽略所有这些参数并提供通用的“asyncio.wait_for”。 (2认同)