Как перестать чинить продакшен после каждого pip install и начать жить спокойно
Знаете этот момент: выкатываете обновление, а приложение падает с загадочной ошибкой. Начинаете копать и выясняете, что библиотека, которая работала вчера, сегодня обновила мажорную версию и сломала обратную совместимость. Классика.
Я через это проходил не раз. Особенно "весело" было в проекте, где зависимости управлялись через pip freeze > requirements.txt после каждого обновления. Что в итоге попадало в репозиторий — загадка. А когда приходилось откатывать версии вручную, потому что "у меня локально всё работает" — это отдельный квест.
Выход есть. И он называется правильное управление зависимостями.
Почему pip freeze — это зло
На первый взгляд всё логично: заморозили текущие версии, закоммитили, всё стабильно. Но проблема в том, что в requirements.txt оказываются ВСЕ установленные пакеты — и те, что вы выбрали явно, и те, что подтянулись как зависимости. В итоге:
- Непонятно, какие библиотеки реально нужны проекту
- Обновление одного пакета тянет кучу транзитивных, которые тоже меняются
- При попытке обновить конкретную библиотеку рискуете сломать всё остальное
Современные инструменты решают эту проблему, разделяя "что мы хотим" и "что у нас есть".
Покажу два подхода, которые использую в зависимости от проекта.
Вариант 1. Poetry (мой фаворит)
Poetry — это не просто менеджер зависимост ей, а полноценный инструмент управления проектом. Он автоматически создает виртуальное окружение, генерирует lock-файл и следит за тем, чтобы у всех разработчиков был одинаковый набор пакетов.
Красота в том, что:
- pyproject.toml хранит только явные зависимости с гибкими ограничениями
- poetry.lock фиксирует точные версии ВСЕХ пакетов
- При обновлении одного пакета Poetry сам пересчитывает зависимости и обновляет lock-файл
Вариант 2. pip-tools (лайт-версия)
Если Poetry кажется избыточным, pip-tools дает похожую логику, но проще.
Здесь:
- requirements.in — ваш список прямых зависимостей (пишете вручную)
- requirements.txt — генерируется автоматически с зафиксированными версиями
- pip-sync приводит окружение в точное соответствие с requirements.txt
Золотое правило, которое я вынес
Lock-файлы должны быть в репозитории. Всегда.
Я видел проекты, где poetry.lock был в .gitignore, потому что "он большой". Это ошибка. Именно lock-файл гарантирует, что на staging, в продакшене и на машине разработчика будут одинаковые версии библиотек.
А вот файлы с прямыми зависимостями (pyproject.toml или requirements.in) — тем более должны быть в репозитории. Это ваша "документация" о том, что проекту реально нужно.
👉🏻 Я в Telegram - t.me/helcode
👉🏻 Я в VK - vk.com/helcode
👉🏻 Я на Boosty - boosty.to/helcode
👉🏻 Я в VK - vk.com/helcode
👉🏻 Я на Boosty - boosty.to/helcode