asyncio - 不止一次等待coroutine(定期任务)

我正在尝试为asyncio事件循环创建一个周期性任务,如下所示,但是我得到一个"RuntimeError: cannot reuse already awaited coroutine"异常 . 显然,asyncio不允许等待this bug thread中讨论的相同的等待功能 . 这就是我尝试实现它的方式:

import asyncio    

class AsyncEventLoop:    

    def __init__(self):
        self._loop = asyncio.get_event_loop()

    def add_periodic_task(self, async_func, interval):
        async def wrapper(_async_func, _interval):
            while True:
                await _async_func               # This is where it goes wrong
                await asyncio.sleep(_interval)
        self._loop.create_task(wrapper(async_func, interval))
        return

    def start(self):
        self._loop.run_forever()
        return

由于我的while循环,将执行相同的等待函数(_async_func),其间有一个休眠间隔 . 我从How can I periodically execute a function with asyncio?获得了周期性任务实施的灵感 .

从上面提到的bug线程中,我推断RuntimeError背后的想法是这样开发人员不会意外地等待两次或更多次相同的协程,因为协程将被标记为已完成并且产生None而不是结果 . 有没有办法可以不止一次等待同一个功能?

回答(1)

2 years ago

看起来你的协同异步函数(协程函数)与协同程序混淆 - 这些异步函数产生的值 .

考虑这个异步函数:

async def sample():
    await asyncio.sleep(3.14)

您正在传递其通话结果: add_periodic_task(sample(), 5) .

相反,您应该传递异步函数对象本身: add_periodic_task(sample, 5) ,并在您的包装器中调用它:

while True:
    await _async_func()
    await asyncio.sleep(_interval)