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

Что будет, если внутри async-функции вызвать блокирующий код?

MiddleКонкурентностьasyncio
Ещё спрашивают так:
  • Как вызвать синхронную библиотеку из asyncio?
  • Зачем нужны asyncio.to_thread и run_in_executor?
Коротко

Встанет весь event loop: блокирующий вызов (time.sleep, requests.get, синхронный драйвер БД, тяжёлое вычисление) не отдаёт управление, и все остальные задачи ждут. Решение — асинхронная библиотека (httpx, asyncpg, aiofiles) или вынос в поток: asyncio.to_thread / loop.run_in_executor.

  • Для CPU-тяжёлого — ProcessPoolExecutor: потоки упрутся в GIL
  • Найти блокировки: asyncio debug mode предупреждает о шагах дольше 100 мс
  • Симптом — растут задержки всех запросов, хотя CPU почти не загружен

А ещё Во FastAPI обычный def-обработчик сам выполняется в пуле потоков, async def — в цикле

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

Подробно

Почему так. Цикл переключает задачи только в точках await. Синхронная функция не содержит await — пока она работает, цикл стоит. Сервер на asyncio с одним requests.get на 2 секунды в обработчике на эти 2 секунды перестаёт отвечать всем.

Варианты решения:

# 1. асинхронная библиотека — лучший вариант
async with httpx.AsyncClient() as client:
    r = await client.get(url)

# 2. блокирующий ввод-вывод — в поток
data = await asyncio.to_thread(legacy_client.fetch, url)

# 3. вычисления — в процесс
loop = asyncio.get_running_loop()
with ProcessPoolExecutor() as pool:
    result = await loop.run_in_executor(pool, heavy_compute, data)

to_thread использует пул потоков цикла по умолчанию (ограниченного размера) — массовые блокирующие вызовы в нём тоже выстроятся в очередь.

Как найти: asyncio.run(main(), debug=True) или PYTHONASYNCIODEBUG=1 логирует «Executing … took 0.5 seconds». В проде — метрика задержки цикла (lag) и профилировщик (py-spy).

Тонкость FastAPI: обработчик, объявленный через def, FastAPI сам запускает в пуле потоков, а async def — прямо в цикле. Блокирующий вызов внутри async def — частая ошибка.

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

  • Блокировка всего цикла и почему.
  • to_thread, run_in_executor, асинхронные библиотеки.
  • Процессы для вычислений.
  • Как обнаружить.

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

  • time.sleep вместо asyncio.sleep.
  • Синхронный драйвер БД в async-обработчике.

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

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

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

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

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

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