Я намагаюся правильно зрозуміти та реалізувати два одночасно запущені Taskоб'єкти, використовуючи відносно новий asyncioмодуль Python 3 .
У двох словах, 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
# 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висловлювання, здається, забезпечують цикл подій опорою для перемикання між завданнями вперед-назад, надаючи ефект паралельності.
Приклад виводу з внутрішнім 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вираз) для того, щоб цикл подій жонглював кількома завданнями?
yield fromнаступногоyield from.