8.16. Подведение итогов

Вы прошли через API asyncio – части, которые нужны скрипту для одновременного выполнения нескольких задач на одном CPU:

  • Кооперативное планирование – модель, на которой держится остальная часть модуля. Выполняющаяся сопрограмма единолично владеет циклом, пока не выполнит await; переключения происходят только в этих точках await.

  • Сопрограммы и задачиasync def определяет единицу работы; asyncio.create_task() планирует её для конкурентного выполнения и возвращает Task, которую приложение может позднее ждать, отменить или идентифицировать.

  • Цикл событий – движок, который выполняет сопрограммы и задачи. asyncio.run() – единственная точка входа, нужная большинству скриптов; класс Loop предоставляет остальное для редких случаев, когда это требуется.

  • Координацияgather() для разветвления и сбора, wait_for() для крайних сроков, Task.cancel и шаблон очистки в предложении finally, распространение исключений через задачи и вызовы gather, а также хук обработчика исключений цикла.

  • Примитивы синхронизацииEvent для сигнализации между сопрограммами, Lock для сериализации доступа к общему ресурсу между операциями await и ThreadSafeFlag для пробуждения задачи asyncio из обработчика прерывания.

  • Пользовательские асинхронные объекты – языковые хуки, которые позволяют классам приложения встраиваться в идиомы asyncio. __await__ для объектов, которые сами являются целью await, __aiter__ / __anext__ для async for и __aenter__ / __aexit__ для async with.

  • Захват кадров – обёртка, которая превращает csi.CSI.snapshot() в дружественную к await сопрограмму, так что цикл захвата выполняется параллельно с другой работой asyncio.

  • Подводные камни – забытые await, плотные циклы без передачи управления, проглоченные отмены, общее состояние, изменяемое между операциями await, и прочие специфичные для asyncio ловушки.

Этого достаточно, чтобы писать программы, сочетающие работу с камерой, аппаратный ввод-вывод и конкурентную фоновую работу в одном цикле.

8.16.1. Использование этого справочника в дальнейшем

Относитесь к главам про asyncio как к справочному материалу; возвращение за формой async with или точным поведением gather() при сбое одной из соседних задач – это и есть предполагаемое использование. Справочная страница модуля asyncio перечисляет каждую функцию и класс в одном месте, когда вопрос состоит лишь в том, «как именно называется этот вызов».

Для более богатых примитивов, построенных поверх модуля – семафоров, очередей, барьеров и солидной коллекции вспомогательных средств прикладного назначения – стандартным источником, поддерживаемым сообществом, является репозиторий peterhinch/micropython-async.

8.16.2. Куда двигаться дальше

Работа с сетью – следующая крупная тема. asyncio.open_connection(), asyncio.start_server() и класс Stream – это то, как скрипт asyncio общается с остальной частью сети изнутри сопрограммы, вместе с лежащими в основе модулями network и socket. Всё, что вы узнали об await, Task, отмене и примитивах синхронизации, переносится сюда напрямую.