Я пытаюсь правильно понять и реализовать два одновременно работающих Task
объектов, используя Python 3 относительно новый asyncio
.
В двух словах asyncio, похоже, предназначен для обработки асинхронных процессов и параллельного выполнения Task
по циклу событий. Это способствует использованию await
(применяется в асинхронных функциях) как обратный вызов для ожидания и использования результата без блокировки цикла события. (Фьючерсы и обратные вызовы по-прежнему являются жизнеспособной альтернативой.)
Он также предоставляет класс asyncio.Task()
, специализированный подкласс Future
, предназначенный для переноса сопрограмм. Предпочтительно вызывается с помощью метода asyncio.ensure_future()
. Предполагаемое использование задач asyncio - позволить независимо запущенным задачам запускаться "одновременно" с другими задачами в пределах одного цикла событий. Я понимаю, что Tasks
связаны с циклом события, который затем автоматически продолжает управлять сопрограммой между операторами await
.
Мне нравится идея использовать одновременные Задачи без необходимости использовать один из классов Executor
, но у меня нет нашел много проработки в отношении реализации.
Вот как я это делаю сейчас:
import asyncio
print('running async test')
async def say_boo():
i = 0
while True:
await asyncio.sleep(0)
print('...boo {0}'.format(i))
i += 1
async def say_baa():
i = 0
while True:
await asyncio.sleep(0)
print('...baa {0}'.format(i))
i += 1
# OPTION 1: wrap in Task object
# -> automatically attaches to event loop and executes
boo = asyncio.ensure_future(say_boo())
baa = asyncio.ensure_future(say_baa())
loop = asyncio.get_event_loop()
loop.run_forever()
В случае попытки одновременного запуска двух задач цикла, я заметил, что, если у задачи нет внутреннего выражения await
, он застрянет в цикле while
, эффективно блокируя выполнение других задач (много как обычный цикл while
). Однако, как только Задачи должны (а) ждать, они, кажется, запускаются одновременно без проблем.
Таким образом, операторы await
, как представляется, обеспечивают цикл событий с плацдармом для переключения между задачами, давая эффект concurrency.
Пример вывода с внутренним await
:
running async test
...boo 0
...baa 0
...boo 1
...baa 1
...boo 2
...baa 2
Пример вывода без внутреннего await
:
...boo 0
...boo 1
...boo 2
...boo 3
...boo 4
Вопросы
Проходит ли эта реализация для "правильного" примера параллельных циклов Задачи в asyncio
?
Правильно ли, что единственный способ, которым это работает, - это Task
предоставить точку блокировки (выражение await
), чтобы цикл события мог манипулировать несколькими задачами?