← Назад к вопросам

В чем проблема команды pip freeze?

2.3 Middle🔥 171 комментариев
#DevOps и инфраструктура#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Проблемы команды pip freeze

Что делает pip freeze

$ pip freeze > requirements.txt
$ cat requirements.txt

certifi==2024.1.9
charset-normalizer==3.3.2
click==8.1.7
flask==3.0.0
idna==3.6
itsdangerous==2.1.2
jinja2==3.1.2
markupsafe==2.1.4
requests==2.31.0
urllib3==2.1.0
werkzeug==3.0.1

pip freeze выводит все установленные пакеты с ТОЧНЫМИ версиями. Выглядит удобно, но есть серьёзные проблемы.

Основные проблемы pip freeze

1. Зависимости от зависимостей (транзитивные зависимости)

Ваш проект:
    ├─ Flask 3.0.0
    │    ├─ click 8.1.7
    │    ├─ jinja2 3.1.2
    │    │    └─ markupsafe 2.1.4
    │    └─ werkzeug 3.0.1
    │         └─ itsdangerous 2.1.2
    │
    └─ requests 2.31.0
         ├─ certifi 2024.1.9
         ├─ charset-normalizer 3.3.2
         └─ urllib3 2.1.0

При pip freeze в requirements.txt попадают ВСЕ пакеты, включая косвенные зависимости:

# requirements.txt (pip freeze)
certifi==2024.1.9       # ← Это зависимость от requests
charset-normalizer==3.3.2  # ← Это зависимость от requests
click==8.1.7            # ← Это зависимость от Flask
flask==3.0.0            # ← ЭТО наш пакет
idna==3.6               # ← Это зависимость от requests
...

Проблема: Невозможно понять, какие пакеты мы установили сами, а какие — автоматические зависимости.

# ✅ Правильный requirements.txt
flask==3.0.0
requests==2.31.0

# ❌ Результат pip freeze
certifi==2024.1.9
charset-normalizer==3.3.2
click==8.1.7
flask==3.0.0
idna==3.6
itsdangerous==2.1.2
jinja2==3.1.2
markupsafe==2.1.4
requests==2.31.0
urllib3==2.1.0
werkzeug==3.0.1

Когда другой разработчик смотрит на ваш requirements.txt, он не понимает, что в нём критично, а что нет.

2. Слишком строгие версии (over-pinning)

pip freeze фиксирует ТОЧНЫЕ версии всех пакетов.

requests==2.31.0  # Именно эта версия, не 2.31.1, не 2.32.0

Это создаёт проблемы:

# Представьте: вышла версия requests 2.31.1 с критическим bugfix
# Но ваш requirements.txt требует 2.31.0 ТОЧНО
# Вы не получите update с исправлением!

pip install -r requirements.txt
# ↓
# Installing requests==2.31.0 (старая версия с багом)

При появлении критического обновления безопасности нужно вручную обновлять версии в requirements.txt.

3. Проблема с Python версиями

# pip freeze не учитывает версии Python
requests==2.31.0
django==4.0.0

Но django==4.0.0 требует Python >= 3.8, а вы разрабатываете на Python 3.7. Когда коллега установит эти зависимости на Python 3.7, получит конфликт версий.

4. Избыточные зависимости для разных платформ

# На Windows:
$ pip install -r requirements.txt
# Установится pywin32 и другие Windows-специфичные пакеты

# На Linux:
$ pip install -r requirements.txt
# Попытается установить pywin32 на Linux (ошибка!)

pip freeze не различает между зависимостями для разработки и production.

5. Локальные пакеты в requirements.txt

$ pip install -e .  # Установили локальный пакет

$ pip freeze
# -e /home/user/myproject

Абсолютный path не будет работать на других компьютерах!

6. Проблема с совместимостью между версиями

# requirements.txt (pip freeze)
package-a==1.0.0
package-b==2.0.0

# Потом выходит package-a 1.1.0, который требует package-b >= 3.0.0
# Но ваш requirements.txt требует package-b==2.0.0 (старая версия)
# Конфликт!

Как правильно управлять зависимостями

Вариант 1: requirements.txt с диапазонами версий

# requirements.txt (правильный)
flask>=3.0.0,<4.0.0    # Совместимо с 3.x, но не 4.x
requests>=2.31.0,<3.0  # Принимаем патч-обновления
sqlalchemy>=2.0.0,<3.0
python>=3.8            # Требуемая версия Python

Таким образом:

  • Вы получаете патч-обновления (2.31.1 с bagfixes)
  • Но не получаете breaking changes (версия 3.0)
  • Коллеги могут установить совместимые версии

Вариант 2: pyproject.toml + poetry

# pyproject.toml
[project]
name = "my-project"
version = "1.0.0"
requires-python = ">=3.8,<3.12"

dependencies = [
    "flask>=3.0.0,<4.0.0",
    "requests>=2.31.0,<3.0",
    "sqlalchemy>=2.0.0,<3.0",
]

[project.optional-dependencies]
dev = [
    "pytest>=7.0",
    "black>=23.0",
    "mypy>=1.0",
]

Плюсы:

  • Явно указана версия Python
  • Разделены основные и dev зависимости
  • Стандарт PEP 621

Вариант 3: pip-compile для pinned версий (production)

# requirements.in (исходный файл)
flask>=3.0,<4.0
requests>=2.31,<3.0

# Генерируем точные версии для production
$ pip-compile requirements.in > requirements.txt

# requirements.txt (сгенерирован)
flask==3.0.0
requests==2.31.0
click==8.1.7
...

Теперь:

  • Вы контролируете зависимости (requirements.in)
  • Точные версии только для production (requirements.txt)
  • Легко обновлять: pip-compile --upgrade

Правильная структура для проекта

project/
├── pyproject.toml           # Основные зависимости
├── requirements-dev.txt     # Dev зависимости (для разработки)
├── requirements.txt         # Production зависимости (опционально)
└── src/
    └── myproject/

pyproject.toml

[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "my-project"
version = "1.0.0"
requires-python = ">=3.9,<3.13"

dependencies = [
    "flask>=3.0,<4.0",
    "requests>=2.31,<3.0",
    "sqlalchemy>=2.0,<3.0",
]

[project.optional-dependencies]
dev = [
    "pytest>=7.0",
    "pytest-cov>=4.0",
    "black>=23.0",
    "ruff>=0.1.0",
    "mypy>=1.0",
    "sphinx>=6.0",
]

[project.urls]
Homepage = "https://github.com/user/my-project"
Issues = "https://github.com/user/my-project/issues"

Когда НА САМОМ ДЕЛЕ использовать pip freeze

1. Docker для production (one-time snapshot)

# Dockerfile
FROM python:3.11-slim

WORKDIR /app
COPY requirements.txt .

# Для production - точные версии
RUN pip install --no-cache-dir -r requirements.txt

COPY . .
CMD ["python", "app.py"]

Генерируем requirements.txt один раз перед деплоем:

pip freeze > requirements.txt
# Коммитим в git
git add requirements.txt
git commit -m "deps: pin versions for production"

2. Документирование для issue reports

# Когда пользователь報告 баг
$ pip freeze > bug_report.txt
# Это помогает разработчикам понять окружение пользователя

Лучшие практики

✅ Делай:

# 1. Используй pyproject.toml для описания зависимостей
# 2. Указывай диапазоны версий, не точные
flask>=3.0,<4.0

# 3. Разделяй dev и production зависимости
# 4. Используй pip-tools для pinned версий только в production
# 5. Регулярно обновляй зависимости
pip list --outdated

❌ Не делай:

# Не используй:
pip freeze > requirements.txt
# для разработки или как основной способ управления зависимостями

# Не коммитай в git:
requests==2.31.0.post1.dev5+local123abc  # Слишком специфично!

# Не используй:
pip install package==*  # Неправильный синтаксис

Пример правильного workflow

# 1. Начинаем проект
poetry init
# или
pip install setuptools wheel
touch pyproject.toml

# 2. Добавляем зависимость
pip install flask
# И добавляем в pyproject.toml:
# dependencies = ["flask>=3.0,<4.0"]

# 3. Для production генерируем точные версии
pip-compile pyproject.toml > requirements.txt

# 4. Коммитим обе файлы
git add pyproject.toml requirements.txt
git commit -m "add dependencies"

# 5. На CI/production используем requirements.txt
pip install -r requirements.txt

# 6. Локально разработчики используют pyproject.toml
pip install -e .[dev]

Заключение

Проблемы pip freeze:

  1. Включает транзитивные зависимости (запутанно)
  2. Слишком строгие версии (блокирует обновления)
  3. Не учитывает Python версию и платформу
  4. Затрудняет управление dev vs production зависимостями

Решение:

  • Используй pyproject.toml с диапазонами версий
  • Используй pip-compile для production pinned версий
  • Только в Docker/CI используй pip freeze для финального snapshot
В чем проблема команды pip freeze? | PrepBro