Да, в показанном запуске asyncio.run() завершает асинхронные генераторы, поэтому Cleanup будет напечатано при завершении работы. Но break сам по себе не гарантирует немедленное выполнение finally генератора.
import asyncio
Да, в показанном запуске asyncio.run() завершает асинхронные генераторы, поэтому Cleanup будет напечатано при завершении работы. Но break сам по себе не гарантирует немедленное выполнение finally генератора.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
import asyncio
usage
async def async_gen(): try: yield 1 yield 2 finally: print("Cleanup")
usage
async def main(): async for x in async_gen(): if x == 1: break print("Done")
if name == "main": asyncio.run(main()) # "Cleanup" напечатается?
Ответ
Да, в показанном запуске asyncio.run() завершает асинхронные генераторы, поэтому Cleanup будет напечатано при завершении работы. Но break сам по себе не гарантирует немедленное выполнение finally генератора.
В этом примере сначала выполняется print('Done'), а cleanup происходит позднее при финализации. Для гарантированной очистки сразу после выхода из цикла используйте явное закрытие:
from contextlib import aclosing
async with aclosing(async_gen()) as values:
async for x in values:
if x == 1:
break
print('Done')
Теперь Cleanup выполняется при выходе из async with до Done, в том же контексте задачи. Не стоит полагаться на момент сборки мусора для освобождения важного ресурса.
Источник: docs.python.org, docs.python.org.