Runners
Исходный код: Lib/asyncio/runners.py
В этом разделе описываются высокоуровневые примитивы asyncio для выполнения кода asyncio.
Они построены поверх цикла событий с целью упростить использование асинхронного кода в распространённых сценариях.
Running an asyncio ProgramЗапуск программы asyncio
- asyncio.run(coro, *, debug=None, loop_factory=None)¶
Выполняет coro в цикле событий asyncio и возвращает результат.
Аргументом может быть любой ожидаемый объект.
Эта функция выполняет ожидаемый объект, управляя циклом событий asyncio, финализируя асинхронные генераторы и закрывая исполнитель.
Эта функция не может быть вызвана, когда в том же потоке выполняется другой цикл событий asyncio.
Если debug равен
True, цикл событий будет запущен в режиме отладки.Falseявно отключает режим отладки.Noneиспользуется для соблюдения глобальных настроек режима отладки.Если loop_factory не равен
None, он используется для создания нового цикла событий; в противном случае используетсяasyncio.new_event_loop(). Цикл закрывается в конце. Эта функция должна использоваться в качестве основной точки входа для программ asyncio, и в идеале должна вызываться только один раз. Рекомендуется использовать loop_factory для настройки цикла событий вместо политик. Передачаasyncio.EventLoopпозволяет запускать asyncio без системы политик.Исполнителю даётся время ожидания 5 минут на завершение. Если исполнитель не завершился за это время, выдаётся предупреждение и исполнитель закрывается.
Пример:
pythonasync def main(): await asyncio.sleep(1) print('hello') asyncio.run(main())Добавлено в версии 3.7.
Изменено в версии 3.9: Обновлено для использования
loop.shutdown_default_executor().Изменено в версии 3.10: debug по умолчанию равен
None, чтобы соответствовать глобальным настройкам режима отладки.Изменено в версии 3.12: Добавлен параметр loop_factory.
Изменено в версии 3.14: coro может быть любым ожидаемым объектом.
Примечание
Система политик
asyncioустарела и будет удалена в Python 3.16; начиная с этой версии, для настройки цикла событий потребуется явный loop_factory.
Runner context managerКонтекстный менеджер Runner
- class asyncio.Runner(*, debug=None, loop_factory=None)¶
Контекстный менеджер, упрощающий многократные вызовы асинхронных функций в одном контексте.
Иногда несколько асинхронных функций верхнего уровня должны вызываться в одном цикле событий и
contextvars.Context.Если debug равен
True, цикл событий будет запущен в режиме отладки.Falseявно отключает режим отладки.Noneиспользуется для соблюдения глобальных настроек режима отладки.loop_factory может использоваться для переопределения создания цикла. Ответственность loop_factory – установить созданный цикл в качестве текущего. По умолчанию используется
asyncio.new_event_loop()и устанавливается в качестве текущего цикла событий с помощьюasyncio.set_event_loop(), если loop_factory равенNone.По сути, пример
asyncio.run()можно переписать с использованием runner:pythonasync def main(): await asyncio.sleep(1) print('hello') with asyncio.Runner() as runner: runner.run(main())Добавлено в версии 3.11.
- run(coro, *, context=None)¶
Выполняет coro во встроенном цикле событий.
Аргументом может быть любой ожидаемый объект.
Если аргумент является корутиной, он обёрнут в задачу.
Необязательный аргумент только по ключевому слову контекст позволяет указать пользовательский
contextvars.Contextдля выполнения кода. Контекст исполнителя по умолчанию используется, если context равенNone.Возвращает результат ожидаемого объекта или вызывает исключение.
Эта функция не может быть вызвана, когда в том же потоке выполняется другой цикл событий asyncio.
Изменено в версии 3.14: coro может быть любым ожидаемым объектом.
- close()¶
Закрывает исполнитель.
Завершает асинхронные генераторы, выключает исполнитель по умолчанию, закрывает цикл событий и освобождает встроенный
contextvars.Context.
- get_loop()¶
Возвращает цикл событий, связанный с экземпляром исполнителя.
Примечание
Runnerиспользует стратегию ленивой инициализации, его конструктор не инициализирует базовые низкоуровневые структуры.Встроенные цикл событий и контекст создаются при входе в тело
withили при первом вызовеrun()илиget_loop().
Handling Keyboard InterruptionОбработка прерывания с клавиатуры
Добавлено в версии 3.11.
Когда signal.SIGINT вызывается с помощью Ctrl-C, исключение KeyboardInterrupt
по умолчанию вызывается в главном потоке. Однако это не работает с
asyncio, потому что это может прервать внутренние механизмы asyncio и может зависнуть программу при завершении.
Чтобы смягчить эту проблему, asyncio обрабатывает signal.SIGINT следующим образом:
asyncio.Runner.run()устанавливает пользовательский обработчикsignal.SIGINTдо выполнения любого пользовательского кода и удаляет его при выходе из функции.Runnerсоздает главную задачу для переданной корутины для её выполнения.Когда
signal.SIGINTвызывается с помощью Ctrl-C, пользовательский обработчик сигнала отменяет главную задачу, вызываяasyncio.Task.cancel(), что вызываетasyncio.CancelledErrorвнутри главной задачи. Это приводит к разворачиванию стека Python, блокиtry/exceptиtry/finallyмогут быть использованы для очистки ресурсов. После отмены главной задачиasyncio.Runner.run()вызываетKeyboardInterrupt.Пользователь может написать тесный цикл, который не может быть прерван
asyncio.Task.cancel(), в этом случае следующий после второго Ctrl-C немедленно вызываетKeyboardInterruptбез отмены главной задачи.