реклама
Бургер менюБургер меню

Юрий Белк – Full stack Developer (страница 16)

18

Но это работает, только если:

– вы включили проверки и не отключаете их «ради скорости»;

– вы используете типы последовательно;

– вы аккуратно работаете с границами (входные данные из внешнего мира).

Практический вывод: типизация в Python – это инструмент качества, который нужно сознательно включать и поддерживать, иначе он «растворяется» в проекте.

Минус 2. Производительность часто ниже; async требует дисциплины

Python обычно медленнее по CPU‑задачам, чем Go/Java/Node (V8 часто быстрее в чистых вычислениях). В прикладном API это не всегда критично, потому что большинство запросов – это I/O:

– база данных;

– кэш;

– внешний сервис.

Но проблемы начинаются, когда:

– в запросе много преобразований данных;

– вы сериализуете/десериализуете большие объёмы JSON;

– вы делаете тяжёлые вычисления в обработчике запроса;

– вы случайно блокируете event loop (в async‑варианте).

Почему «async требует дисциплины»

FastAPI и современный Python‑стек часто используют `async`/`await`. Это мощно, но легко ошибиться:

– вы используете синхронную библиотеку внутри `async`‑эндпоинта;

– вы делаете блокирующий вызов (например, обычный HTTP‑клиент без async);

– вы запускаете CPU‑тяжёлое в том же потоке;

– вы не контролируете время ожидания и ретраи.

Снаружи это проявляется как странные симптомы:

– сервис «живой», но отвечает медленно;

– под нагрузкой резко растут задержки;

– метрики показывают, что CPU не загружен на 100%, но запросы висят.

Проблема не в том, что async «плохой». Проблема в том, что в Python легко смешать async и sync так, что вы сами себе создаёте пробки.

Обычно помогают практики:

– чётко выбирать: этот сервис в основном async или в основном sync;

– использовать подходящие библиотеки (async‑драйверы БД, async‑HTTP клиент);

– выносить CPU‑тяжёлое в фоновые воркеры;

– ограничивать параллелизм и ставить таймауты.

Минус 3. Параллелизм сложнее (GIL), обычно уходят в процессы/очереди

В Python есть известная особенность: GIL (Global Interpreter Lock) в CPython. Упрощённо: в одном процессе Python‑код не исполняется параллельно на нескольких ядрах так, как вы могли бы ожидать от потоков.

Что это значит для бэкенда:

– Для I/O‑нагрузки это часто не критично: пока вы ждёте сеть/БД, можно обрабатывать другие запросы.

– Для CPU‑нагрузки это становится проблемой: если у вас тяжёлая обработка данных, один процесс будет упираться в одно ядро.

Типичные решения в продакшене:

1) Масштабирование процессами

Запускают несколько воркеров веб‑сервера (несколько процессов). Это даёт использование нескольких ядер.

2) Очереди и фоновые задачи

CPU‑тяжёлое выносят из HTTP‑обработчика в отдельные воркеры: так API остаётся быстрым, а тяжёлая работа выполняется асинхронно.

3) Отдельные сервисы для тяжёлых расчётов

Иногда проще вынести вычисления в отдельный компонент (на другом языке или в отдельной инфраструктуре), чем бороться с ограничениями внутри одного API.

4) Нативные расширения

Для некоторых задач используют библиотеки, которые внутри реализованы на C/C++/Rust и обходят ограничения, потому что тяжёлая часть выполняется вне интерпретатора.

Практическая мысль: Python отлично работает как «клей» и как слой бизнес‑логики, но если ваш сервис – это постоянные тяжёлые вычисления на запрос, вам почти наверняка понадобится отдельная стратегия параллелизма.

Минус 4. Управление зависимостями и окружением может быть источником боли

Это не уникально для Python, но в Python это встречается чаще из‑за большого количества способов «как правильно» управлять пакетами.

В реальных проектах проблемы выглядят так:

– «у меня локально работает, в CI нет»;

– «после обновления зависимости всё сломалось»;

– «на сервере другая версия Python»;

– «библиотека тянет несовместимые версии зависимостей».

Эта боль сильно уменьшается, если:

– фиксировать версии зависимостей;

– использовать виртуальные окружения;

– контейнеризировать приложение;

– иметь понятный способ сборки (один, а не три разных в разных командах).

2.4. Когда выбирать Python

Сценарий 1. Продукты с аналитикой/ML и плотной работой с данными

Если в продукте важны:

– рекомендации;

– скоринг;

– сегментации пользователей;

– обработка событий и метрик;