asyncio: get_running_loop внутри run_until_complete
@python_quizРазберем этот квиз
Коротко — программа напечатает True. Ниже разберём почему, пошагово разберём варианты ответов и покажем небольшие примеры.
Условие (код)

Что происходит шаг за шагом
- Создаётся новый цикл событий
loop = asyncio.new_event_loop(). asyncio.set_event_loop(loop)назначает этот цикл как "текущий" в контексте модуля asyncio (в этой нити).- Запускаем корутину
mainна созданном цикле черезloop.run_until_complete(main()). На время выполненияrun_until_completeцикл считается запущенным. - Внутри
main()вызываетсяasyncio.get_running_loop(). Эта функция возвращает *запущенный* цикл событий в текущей нити — то, на котором реально выполняется корутина. - Так как мы запускаем
main()именно на объектеloop, сравнениеasyncio.get_running_loop() is loopдастTrue.
Почему не False и не RuntimeError
- False бы получилось только если внутри корутины был бы запущен другой цикл или
get_running_loop()вернул бы другой объект (например, если бы корутина выполнялась на другом loop), чего тут не происходит. RuntimeErrorвозникает, когда пытаются получить "запущенный" цикл там, где он не запущен (например, вызовasyncio.get_running_loop()в обычной функции вне запущенного цикла). В данном коде вызов происходит внутри корутины, запущенной черезrun_until_complete, поэтому ошибки не будет.- Вызов
set_event_loop(loop)здесь не обязателен для полученияTrue: даже если не вызыватьset_event_loop, вызовloop.run_until_complete(main())делаетloopзапущенным для текущей нити, и внутри корутиныget_running_loop()вернёт тот жеloop.
Разбор вариантов (коротко)
- Выведет
False— неправдоподобно для данного кода, потому что запущенный цикл — тот же объектloop. - Выведет
True— соответствует описанному поведению: внутри запущенной корутиныget_running_loop()возвращает запущенный цикл. - Поднимет
RuntimeErrorдо запускаmain()— не соответствует:RuntimeErrorдля get_running_loop возникает при вызове вне запущенного цикла, но в коде вызов происходит внутри уже запускаемого цикла. - Поднимет
RuntimeErrorвнутриmain()— не происходит, так как внутриmain()цикл запущен.
Наглядные примеры
Оригинальный код — печатает True:

Вызов get_running_loop вне запущенного цикла — RuntimeError:

Альтернатива с get_event_loop (поведение зависит от версии Python и контекста):

Итог
В рассматриваемом коде внутри выполняющейся корутины вызывается asyncio.get_running_loop(), и поскольку корутина запущена на объекте loop, сравнение с loop вернёт True. Важно понимать разницу между "текущим" циклом (set_event_loop / get_event_loop) и именно "запущенным" циклом (get_running_loop), особенно при отладке ошибок вида RuntimeError: no running event loop.