asyncio - ждите сопрограмму более одного раза (периодические задания) - PullRequest
0 голосов
/ 30 июня 2018

Я пытаюсь создать периодическое задание для цикла событий asyncio, как показано ниже, однако я получаю исключение «RuntimeError: не могу повторно использовать уже ожидаемую подпрограмму». По-видимому, asyncio не позволяет ожидать той же ожидаемой функции, как обсуждалось в этой ветке ошибок . Вот как я пытался это реализовать:

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) будет выполняться с интервалом ожидания между ними. Я получил вдохновение для выполнения периодических задач от Как я могу периодически выполнять функцию с помощью asyncio? .

Из упомянутой выше ветки ошибок я делаю вывод, что идея RuntimeError заключалась в том, чтобы разработчики случайно не ожидали одну и ту же сопрограмму дважды или более, поскольку сопрограмма будет помечена как выполненная и выдаст None вместо результата. Есть ли способ, которым я могу ожидать одну и ту же функцию более одного раза?

1 Ответ

0 голосов
/ 30 июня 2018

Похоже, вы путаете асинхронные функции (функции сопрограмм) с сопрограммами - значениями, которые производят эти асинхронные функции.

Рассмотрим эту асинхронную функцию:

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)
...