Получить доступ

Как работают async и await?

JuniorКонкурентностьasyncio
Ещё спрашивают так:
  • Что такое корутина?
  • Что такое event loop?
  • Как запустить несколько корутин одновременно?
Коротко

async def создаёт корутину, await — точка, где она отдаёт управление циклу событий, пока ждёт.

  • Цикл событий переключается между корутинами в точках await — в одном потоке
  • Одновременный запуск: asyncio.gather или asyncio.TaskGroup (3.11+)

А ещё Блокирующий вызов (time.sleep, синхронный HTTP) останавливает все корутины

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Подробно

Вызов функции, объявленной через async def, не выполняет её тело, а возвращает объект-корутину. Выполнить его можно через await внутри другой корутины или запустив цикл событий: asyncio.run(main()).

Цикл событий (event loop) держит список задач. Корутина выполняется до ближайшего await на операции, которая ещё не готова (ответ сети, таймер). Там она приостанавливается, цикл запускает другую готовую задачу, а когда операция завершается — продолжает первую с того же места. Переключение кооперативное: корутина сама решает, где уступить, и только в await.

Одновременность. Последовательные await a(); await b() идут друг за другом. Чтобы задачи шли параллельно, их оборачивают в задачи: asyncio.gather(a(), b()), asyncio.create_task(...) или TaskGroup — последний правильно отменяет остальные задачи при ошибке.

Ограничения. await можно писать только внутри async def. Всё блокирующее внутри корутины останавливает цикл целиком: вместо time.sleep — asyncio.sleep, вместо requests — aiohttp или httpx. Блокирующий код, без которого не обойтись, выносят в поток: await asyncio.to_thread(func).

asyncio не ускоряет вычисления — это способ эффективно ждать много операций ввода-вывода.

Пример

import asyncio

async def fetch(name, delay):
    await asyncio.sleep(delay)          # не блокирует другие корутины
    return f"{name} готов"

async def main():
    # последовательно — 3 секунды
    await fetch("a", 1)
    await fetch("b", 2)

    # параллельно — 2 секунды
    results = await asyncio.gather(fetch("a", 1), fetch("b", 2))
    print(results)

asyncio.run(main())

Что хотят услышать

  • Что такое корутина и что вызов async def её только создаёт.
  • Роль цикла событий и кооперативное переключение в await.
  • Как запустить задачи параллельно.
  • Опасность блокирующих вызовов и способ их вынести.

Частые ошибки

  • Забыть await — корутина не выполнится, будет предупреждение.
  • Ожидать, что asyncio ускорит вычисления на CPU.

Что спросят дальше

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем