Основы окружений
~25 мин

Python окружения

pip, poetry, uv, pyenv, venv — как работает, зачем нужно, чем отличаются.

Python окружения — чтобы "у меня работает" работало у всех

Загрузка интерактивного виджета...

Ты клонировал репозиторий коллеги, написал pip install -r requirements.txt, а всё падает с ошибками версий. Знакомо? Проблема простая: scikit-learn хочет numpy>=1.21, а старый TensorFlow — numpy<1.20. Они не уживаются в одном окружении. Виртуальные окружения решают это — каждый проект живёт в своём изолированном «пузыре» с собственными пакетами. Конфликтов нет, воспроизводимость гарантирована.

venv + pyenv — базовые инструменты

venv идёт в комплекте с Python — ничего устанавливать не нужно. Создаёт папку с копией интерпретатора и изолированными пакетами. Для маленьких проектов и скриптов — вполне хватает. А pyenv решает другую задачу: если один проект требует Python 3.9, а другой — 3.12, pyenv ставит несколько версий и позволяет переключаться. Команда pyenv local создаёт файл .python-version — и Python в этой папке автоматически нужной версии.

⚠️ Не коммить .venv в git

Папка .venv — это гигабайты бинарников, они привязаны к ОС. В git идёт только requirements.txt (или pyproject.toml). Добавь .venv/ в .gitignore. Коллега сделает pip install -r requirements.txt и получит своё окружение.

Poetry и uv — современные менеджеры зависимостей

pip — стандартный менеджер, но у него нет нормального lock-файла из коробки. pip freeze фиксирует версии, но не гарантирует, что через месяц зависимости разрешатся так же. Poetry и uv решают эту проблему: один файл pyproject.toml описывает проект, а lock-файл фиксирует точные версии ВСЕХ зависимостей (включая транзитивные). У тебя Python 3.11 на Mac, у коллеги Python 3.11 на Linux — poetry install или uv sync поставит одинаковые версии обоим.

Ниже — пример типичного workflow с uv (самый быстрый инструмент, написан на Rust). С poetry команды аналогичны: poetry init, poetry add, poetry install, poetry run.

# Создать проект с uv (или poetry init для poetry)
uv init ml-project && cd ml-project

# Добавить зависимости — uv сам разрешит версии
uv add pandas scikit-learn torch
uv add --dev pytest ruff    # dev-зависимости отдельно

# Установить окружение из lock-файла (детерминированно!)
uv sync

# Запустить скрипт в окружении
uv run python train.py

# Управление Python-версиями (встроено в uv, как pyenv)
uv python install 3.12
uv python pin 3.11

Результат — pyproject.toml с описанием проекта и зависимостей. Это единый стандартный файл, который понимают и poetry, и uv, и pip. Lock-файл (uv.lock или poetry.lock) фиксирует точные версии всех пакетов — именно он даёт воспроизводимость.

# pyproject.toml — всё в одном файле
[project]
name = "ml-project"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = [
    "pandas>=2.2",
    "scikit-learn>=1.4",
    "mlflow>=2.11",
]

[project.optional-dependencies]
dev = ["pytest>=8.0", "ruff>=0.3"]

💡 Что выбрать в 2025?

Новый проект → uv (быстрый, современный, заменяет pip + pyenv + venv в одном). Существующий проект с poetry → оставайся на poetry (стабильно, проверено). Маленький скрипт → pip + venv (просто и достаточно). conda → если нужны не-Python зависимости (CUDA, системные C-библиотеки для научных пакетов).

Сравнение инструментов

  • pip + venv — просто, нет lock-файла, медленный. Для скриптов и маленьких проектов
  • poetry — lock-файл, группы зависимостей, публикация пакетов. Стандарт для production-проектов
  • uv — lock-файл, управление Python, молниеносная скорость. Новый стандарт для 2025+
  • conda — для научных пакетов с C-зависимостями (CUDA, MKL). Тяжёлый, отдельная экосистема
  • pyenv — только управление версиями Python. Не нужен, если используешь uv

💡 Как это в реальной работе

Ты клонируешь репозиторий ML-проекта, видишь pyproject.toml — делаешь uv sync (или poetry install) и через 30 секунд у тебя рабочее окружение. Все версии зафиксированы в lock-файле — у тебя и коллеги одинаковые пакеты. В Docker-образе тоже uv sync — воспроизводимость от ноутбука до прода.

🎯 На собесе

Как вы управляете зависимостями в ML-проекте? Хороший ответ: pyproject.toml + lock-файл (poetry или uv). Отдельные окружения для каждого проекта. Dev-зависимости (pytest, ruff) отделены от prod-зависимостей. Версии зафиксированы для воспроизводимости.