Автор оригинала: Doug Hellmann.
Задачи – один из основных способов взаимодействия с циклом событий. Задачи обертывают сопрограммы и отслеживают их выполнение. Задачи являются подклассами Future
, поэтому другие сопрограммы могут их ждать, и каждая из них имеет результат, который можно получить после завершения задачи.
Запуск задачи
Чтобы запустить задачу, используйте create_task ()
для создания экземпляра Task
. Результирующая задача будет выполняться как часть параллельных операций, управляемых циклом событий, пока цикл выполняется и сопрограмма не возвращается.
asyncio_create_task.py
import asyncio async def task_func(): print('in task_func') return 'the result' async def main(loop): print('creating task') task loop.create_task(task_func()) print('waiting for {!r}'.format(task)) return_value await task print('task completed {!r}'.format(task)) print('return value: {!r}'.format(return_value)) event_loop asyncio.get_event_loop() try: event_loop.run_until_complete(main(event_loop)) finally: event_loop.close()
В этом примере перед завершением работы функции main ()
ожидается, пока задача не вернет результат.
$ python3 asyncio_create_task.py creating task waiting for> in task_func task completed > return value: 'the result'
Отмена задачи
Сохраняя объект Task
, возвращенный из create_task ()
, можно отменить операцию задачи до ее завершения.
asyncio_cancel_task.py
import asyncio async def task_func(): print('in task_func') return 'the result' async def main(loop): print('creating task') task loop.create_task(task_func()) print('canceling task') task.cancel() print('canceled task {!r}'.format(task)) try: await task except asyncio.CancelledError: print('caught error from canceled task') else: print('task result: {!r}'.format(task.result())) event_loop asyncio.get_event_loop() try: event_loop.run_until_complete(main(event_loop)) finally: event_loop.close()
В этом примере создается и затем отменяется задача перед запуском цикла событий. Результатом является исключение CancelledError
из run_until_complete ()
.
$ python3 asyncio_cancel_task.py creating task canceling task canceled task> caught error from canceled task
Если задача отменяется во время ожидания другой параллельной операции, задача уведомляется о ее отмене, вызывая исключение CancelledError
в точке, где она ожидает.
asyncio_cancel_task2.py
import asyncio async def task_func(): print('in task_func, sleeping') try: await asyncio.sleep(1) except asyncio.CancelledError: print('task_func was canceled') raise return 'the result' def task_canceller(t): print('in task_canceller') t.cancel() print('canceled the task') async def main(loop): print('creating task') task loop.create_task(task_func()) loop.call_soon(task_canceller, task) try: await task except asyncio.CancelledError: print('main() also sees task as canceled') event_loop asyncio.get_event_loop() try: event_loop.run_until_complete(main(event_loop)) finally: event_loop.close()
Перехват исключения дает возможность при необходимости очистить уже выполненную работу.
$ python3 asyncio_cancel_task2.py creating task in task_func, sleeping in task_canceller canceled the task task_func was canceled main() also sees task as canceled
Создание задач из сопрограмм
Функция sure_future ()
возвращает Task
, привязанную к выполнению сопрограммы. Затем этот экземпляр Task
можно передать другому коду, который может ждать его, не зная, как была создана или вызвана исходная сопрограмма.
asyncio_ensure_future.py
import asyncio async def wrapped(): print('wrapped') return 'result' async def inner(task): print('inner: starting') print('inner: waiting for {!r}'.format(task)) result await task print('inner: task returned {!r}'.format(result)) async def starter(): print('starter: creating task') task asyncio.ensure_future(wrapped()) print('starter: waiting for inner') await inner(task) print('starter: inner returned') event_loop asyncio.get_event_loop() try: print('entering event loop') result event_loop.run_until_complete(starter()) finally: event_loop.close()
Обратите внимание, что сопрограмма, переданная в sure_future ()
, не запускается, пока что-то не использует await
, чтобы разрешить ее выполнение.
$ python3 asyncio_ensure_future.py entering event loop starter: creating task starter: waiting for inner inner: starting inner: waiting for> wrapped inner: task returned 'result' starter: inner returned