8.13. Управление циклом

Большинство asyncio-скриптов никогда не обращаются к циклу событий напрямую – достаточно asyncio.run(). Эта страница описывает интерфейс Loop для случаев, когда этого недостаточно: установка обработчика исключений, запуск цикла с иным жизненным циклом, чем у run, или сохранение объекта цикла для инструментирования.

8.13.1. Получение цикла

  • asyncio.get_event_loop() – возвращает объект Loop. Безопасно вызывать как изнутри корутины, так и снаружи.

  • asyncio.new_event_loop() – в MicroPython сбрасывает состояние существующего цикла, а не создаёт новый. Повторим примечание: на программу приходится ровно один цикл событий.

Не существует API для запуска цикла, кроме методов Loop и asyncio.run().

8.13.2. Прямой запуск цикла

asyncio.run() – правильная точка входа почти для каждого приложения. Для случаев, когда это не так, существуют два метода Loop.

  • run_until_complete() – получив ожидаемый объект, выполняет цикл, пока этот объект не завершится, затем возвращает его результат. Эквивалентно одному вызову asyncio.run(), но без завершающего разрушения цикла.

  • run_forever() – выполняет цикл, пока изнутри задачи не будет вызван stop(). Нет ожидаемого объекта верхнего уровня; ожидается, что приложение запланирует всё необходимое через asyncio.create_task() перед вызовом run_forever.

Сопутствующие методы – это stop() (запросить остановку цикла после завершения текущей задачи) и close() (освободить ресурсы цикла).

8.13.3. Создание задач на стороне цикла

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

8.13.4. Обработчики исключений

Цикл вызывает обработчик, когда задача возбуждает исключение, которое ничто в цепочке вызовов корутин не перехватило – типичный случай – это задача, которую приложение создало через asyncio.create_task() и так и не ожидало. Обработчик по умолчанию печатает трассировку через sys.stderr; на странице исключения было показано, как заменить его на что-то своё.

  • set_exception_handler() – установить пользовательский обработчик. Обработчик – это вызываемый объект handler(loop, context), где context – это dict, содержащий как минимум 'message' и обычно 'exception' и 'future'.

  • get_exception_handler() – возвращает установленный в данный момент обработчик или None, если используется обработчик по умолчанию.

  • default_exception_handler() – встроенный обработчик. Полезен внутри пользовательского обработчика, который хочет также выполнить поведение по умолчанию (например, записать в флеш-память и напечатать трассировку).

  • call_exception_handler() – запускает установленный в данный момент обработчик с вручную построенным словарём контекста. В основном используется самим циклом; приложению он редко нужен.