asyncio - 多次等待协程(周期性任务) [英] asyncio - await coroutine more than once (periodic tasks)

查看:115
本文介绍了asyncio - 多次等待协程(周期性任务)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为 asyncio 事件循环创建一个周期性任务,如下所示,但是我收到了RuntimeError:无法重用已经等待的协程"异常.显然,asyncio 不允许等待与 此错误线程 中讨论的相同的可等待函数.这是我尝试实现它的方式:

I am trying to create a periodic task for an asyncio event loop as shown below, however I am getting a "RuntimeError: cannot reuse already awaited coroutine" exception. Apparently, asyncio does not allow for the same awaitable function to be awaited as discussed in this bug thread. This is how I tried to implement it:

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 to使用 asyncio 定期执行函数?.

Because of my while loop, the same awaitable function (_async_func) would be executed with a sleep interval in between. I got my inspiration for the implementation of periodic tasks from How can I periodically execute a function with asyncio? .

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

From the bug thread mentioned above, I infer that the idea behind the RuntimeError was so that developers wouldn't accidentally await the same coroutine twice or more, as the coroutine would be marked as done and yield None instead of the result. Is there a way I can await the same function more than once?

推荐答案

您似乎将异步函数(协程函数)与协程(这些异步函数产生的值)混淆了.

It seems you are confusing async functions (coroutine functions) with coroutines - values that these async functions produce.

考虑这个异步函数:

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

您正在传递其调用的结果:add_periodic_task(sample(), 5).

You are passing result of its call: add_periodic_task(sample(), 5).

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

Instead, you should pass async function object itself: add_periodic_task(sample, 5), and call it within your wrapper:

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

这篇关于asyncio - 多次等待协程(周期性任务)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆