Определение последовательности вывода при использовании asyncio.gather

Первой появится f2: её длинный цикл не содержит await и блокирует event loop. Даже если секунда сна f1 уже прошла, f1 не сможет продолжиться, пока f2 не отдаст управление.

Короткий ответ

Что ответить на собеседовании

Первой появится f2: её длинный цикл не содержит await и блокирует event loop. Даже если секунда сна f1 уже прошла, f1 не сможет продолжиться, пока f2 не отдаст управление.

Подробный разбор

Ответ с пояснениями

Условие

Какой вывод появится в консоли первым и почему?

import asyncio

async def f1():
    await asyncio.sleep(1)
    print("f1")

async def f2():
    for _ in range(1_000_000_000):
        pass
    print("f2")

async def main():
    await asyncio.gather(f1(), f2())

asyncio.run(main())

Ответ

Первой появится f2: её длинный цикл не содержит await и блокирует event loop. Даже если секунда сна f1 уже прошла, f1 не сможет продолжиться, пока f2 не отдаст управление.

gather планирует обе корутины, но не превращает CPU-работу в параллельное выполнение. f1 начинает sleep и уступает управление; f2 крутит цикл до конца и печатает f2. Затем f1 получает возможность напечатать f1.

Если цикл неожиданно займёт меньше секунды, f1 просто дождётся остатка таймера, порядок останется тем же. CPU-тяжёлую работу обычно выносят в процесс или специализированный исполнитель. Само добавление async к функции не делает её неблокирующей.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее