async и await
Тема дорожной карты · Python Programming
Асинхронное программирование с использованием async и await позволяет эффективно обрабатывать I/O-ограниченные задачи и конкурентные операции, что делает его ключевым инструментом для современных приложений. В Python это реализуется через модуль asyncio, который предоставляет однопоточный цикл событий для выполнения асинхронных корутин.
async def объявляет корутину, а await приостанавливает её до завершения другой ожидаемой задачи и в это время позволяет циклу событий выполнять другие задачи. await допустим только внутри функции, объявленной с помощью async def, и только над объектами, которые поддерживают ожидание (awaitable). Частая ошибка — забытый await: вместо результата вы получите объект корутины, который никогда не запустится. Не вызывайте блокирующий синхронный код (time.sleep, requests.get) внутри корутин — он заморозит цикл событий. Для выполнения CPU-нагрузки используйте asyncio.to_thread или пул процессов.
Как это работает
async и await используют модуль asyncio (введен с Python 3.4) — однопоточный цикл событий, исполняющий корутины (функции async def). await приостанавливает корутину до завершения awaitable-объекта; в это время цикл событий переключается на выполнение других готовых задач. Tasks (asyncio.create_task) позволяют конкурентно запускать корутины; asyncio.gather(*tasks) ждет завершения множества задач параллельно. Асинхронные библиотеки (aiohttp, asyncpg, httpx) заменяют блокирующие аналоги. Синхронный код блокирует цикл событий — никогда не вызывайте time.sleep или requests.get внутри async def.
Когда применять
Используйте асинхронное программирование, когда нагрузка I/O-ограниченная и конкурентная — тысячи HTTP-запросов, WebSocket fan-out, скрейпинг, асинхронный доступ к базам данных во веб-фреймворке (например, FastAPI). Для задач с высокой CPU-нагрузкой асинхронное программирование не поможет — в таких случаях лучше использовать multiprocessing или внешние воркеры. Для простых линейных скриптов с несколькими HTTP-вызовами синхронный requests может быть короче и проще для отладки; асинхронное программирование окупается при наличии ~50+ конкурентных операций.
Типичные ошибки
Ключевые ловушки при использовании async и await включают смешение синхронного блокирующего кода в асинхронном контексте (один time.sleep(1) замораживает весь цикл событий); запуск неограниченного количества задач без обратной связи (память может взорваться); забытый await — вы получите объект корутины, который никогда не запустится (Python 3.11+ предупреждает об этом); неосторожное смешивание потоков и асинхронного кода (asyncio.run_in_executor существует для блокирующих вызовов — используйте его). Для дебага используйте PYTHONASYNCIODEBUG=1 и asyncio.Task.get_stack().
Связанные понятия
Полезные ресурсы
Проверить знания (1)
Загрузка вопросов…