asyncio ломается не там, где «не работает await», а там, где смешивают блокировки
За неделю в репах чаще всего всплывают одни и те же ошибки:
— внутри async-функции вызывают обычный `requests`, `time.sleep`, тяжёлый JSON-парсинг;
— делают много задач через `create_task`, но не собирают их и теряют исключения;
— запускают всё подряд без лимита, а потом удивляются, почему сервис «встал».
Правило простое: если код ждёт сеть или диск — это кандидат на `await`; если он жрёт CPU — выносите его из event loop. Для блокирующих библиотек используйте `run_in_executor` или отдельный воркер, иначе один долгий вызов тормозит всю очередь. И ещё: `asyncio.gather` удобен, но без контроля ошибок и отмены он легко превращается в источник тихих падений.
Отдельно проверьте границы. Если задачу можно отменить — обрабатывайте `CancelledError`, если нельзя — не делайте вид, что можно. Для параллелизма почти всегда нужен лимит через `Semaphore`, а не «чем больше корутин, тем быстрее» 🙂
Лучший тест на зрелость async-кода: можно ли выключить один внешний сервис, не положив весь процесс. Если нет — проблема не в asyncio, а в архитектуре.
Python Web & Scripts — Django, FastAPI, скрипты
@python_web_scripts
asyncio ломается не там, где «не работает await», а там, где смешивают блокировки
Этот пост опубликован в Telegram-канале Python Web & Scripts — Django, FastAPI, скрипты. Подписаться можно по ссылке: @python_web_scripts.