Сообщить об ошибке.

Создание, запуск и остановка цикла событий низкоуровневым API asyncio

В разделе рассмотрены методы объекта цикла событий, связанные с его запуском и остановкой. Прежде чем запускать и останавливать цикл событий, его необходимо создать или получить функциями, описанными в разделе "Создание и получение текущего цикла событий".

Примечание. Разработчики приложений, для запуска цикла событий асинхронного кода, должны использовать высокоуровневую функцию asyncio.run(), так как редко нужно ссылаться на объект цикла или вызывать его методы. Низкоуровневый API предназначен для авторов библиотек и фреймворков, которым требуется более тонкий контроль над поведением цикла событий.

Методы, связанные с запуском и остановкой цикла событий:


loop.run_until_complete(future):

Метод loop.run_until_complete() запускает цикл событий, пока не завершится Future (экземпляр Future).

Если аргумент future является объектом сопрограммы, то он неявно планируется для запуска как asyncio.Task.

Метод loop.run_until_complete() возвращает результат Future или вызывает его исключение.

loop.run_forever():

Метод loop.run_forever() Запускайте цикл обработки событий до вызова метода loop.stop().

Если метод loop.stop() вызывается до вызова loop.run_forever(), то цикл один раз опрашивает селектор ввода-вывода с нулевым таймаутом, запускает все обратные вызовы, запланированные в ответ на события ввода-вывода (и те, которые уже были запланированы), и затем завершится.

Если метод loop.stop() вызывается во время работы loop.run_forever(), цикл выполнит текущий пакет обратных вызовов и затем завершится. Обратите внимание, что новые обратные вызовы, запланированные обратными вызовами, в этом случае не будут выполняться. Вместо этого они будут запущены при следующем вызове loop.run_forever() или loop.run_until_complete().

loop.stop():

Метод loop.stop() останавливает цикл событий.

loop.is_running():

Метод loop.is_running() возвращает True, если цикл событий в данный момент запущен.

loop.is_closed():

Метод loop.is_closed() возвращает True, если цикл событий был закрыт.

loop.close():

Метод loop.close() закрывает цикл событий.

При вызове этой функции цикл не должен выполняться. Все ожидающие обратные вызовы будут отклонены.

Этот метод очищает все очереди и завершает работу исполнителя, и не дожидается завершения работы исполнителя.

Этот метод идемпотентен и необратим. Никакие другие методы не должны вызываться после закрытия цикла событий.

loop.shutdown_asyncgens():

Метод loop.shutdown_asyncgens() планирует закрытие всех открытых в данный момент объектов асинхронного генератора с помощью вызова его метода .aclose(). После вызова этого метода, цикл событий выдаст предупреждение, если будет выполняться итерация нового асинхронного генератора.

Метод следует использовать для надежного завершения всех запланированных асинхронных генераторов. Представляет собой сопрограмму, которую можно запускать с помощью оператора await или обернуть в задачу.

Обратите внимание, что при использовании asyncio.run() нет необходимости вызывать эту функцию.

try:
    loop.run_forever()
finally:
    loop.run_until_complete(loop.shutdown_asyncgens())
    loop.close()

Новое в Python 3.6.

loop.shutdown_default_executor(timeout=None):

Новое в Python 3.9.

Изменено в Python 3.12: Добавлен аргумент timeout.

Метод loop.shutdown_default_executor() планирует закрытие исполнителя по умолчанию и дожидается, пока он присоединится ко всем потокам в ThreadPoolExecutor. После вызова этого метода будет вызвана ошибка RuntimeError, если loop.run_in_executor() вызывается при использовании исполнителя по умолчанию.

Метод представляет собой сопрограмму, которую можно запускать с помощью оператора await или обернуть в задачу.

Аргумент timeout (добавлен в Python 3.12) указывает количество времени (в секундах float), которое будет предоставлено исполнителю для завершения присоединения. При значении по умолчанию timeout=None исполнителю разрешено неограниченное количество времени.

Если тайм-аут достигнут, то выдается RuntimeWarning, и исполнитель по умолчанию завершается, не дожидаясь завершения соединения своих потоков.

Примечание. Не вызывайте этот метод при использовании asyncio.run(), поскольку последний автоматически обрабатывает завершение работы исполнителя по умолчанию.

Пример запуска и остановки цикла событий низкоуровневым API.

import asyncio

async def worker_io():
    print('Старт ожидания ответа сервера')
    res = await asyncio.sleep(2, result=200)
    print(f'Сервер ответил c результатом {res}')
    return f'worker_io => {res}'

async def other_worker():
    print('Делаем что-то другое...')
    res = await asyncio.sleep(1.5, result=15)
    print(f'Другая работа закончена...')
    return f'other_worker => {res}'

if __name__ == '__main__':
    # создаем цикл событий
    loop = asyncio.get_event_loop()
    try:
        # создаем задачи 
        task1 = loop.create_task(worker_io())
        task2 = loop.create_task(other_worker())
        # объединяем задачи в группу, для 
        # планирования асинхронного выполнения
        group =  asyncio.gather(task1, task2)
        # получаем результаты
        return_value = loop.run_until_complete(group)
        print(f'Результаты работы сопрограмм: {return_value!r}')
    finally:    
        # останавливаем цикл событий
        loop.close()


# Старт ожидания ответа сервера
# Делаем что-то другое...
# Другая работа закончена...
# Сервер ответил c результатом 200
# Результаты работы сопрограмм: ['worker_io => 200', 'other_worker => 15']