Какие инструменты используются для управления окружением и зависимостями в Python?
Что проверяют
Понимаете ли вы разницу между изоляцией окружения, установкой пакетов и фиксацией версий, и умеете ли сделать сборку воспроизводимой. Следом обычно спрашивают, чем lock-файл отличается от requirements.txt из pip freeze и что вы выберете для нового проекта.
Как отвечать
Разложите по задачам:
- версия интерпретатора:
pyenvилиuv python install, в Docker просто нужный базовый образ; - изоляция:
venvиз стандартной библиотеки илиvirtualenv. В свежих Debian и Ubuntu системныйpipвне окружения откажется ставить пакеты с ошибкойexternally-managed-environment(PEP 668); - описание зависимостей:
pyproject.tomlс секцией[project]по PEP 621, прямые зависимости с диапазонами версий; - фиксация: lock-файл с точными версиями всех транзитивных пакетов и хэшами. Это
uv.lock,poetry.lockилиrequirements.txtизpip-compile(pip-tools), а единым форматом сталpylock.tomlпо PEP 751; - менеджеры целиком: uv (написан на Rust, очень быстрый, заменяет pip, venv, pip-tools и pyenv:
uv add,uv lock,uv sync), Poetry (со второй версии понимает стандартную секцию[project]), PDM, Hatch. Pipenv встречается в старых проектах; - conda или mamba: когда нужны бинарные зависимости не из мира Python, типичный случай в Data Science;
- pipx или
uv tool: для консольных утилит вродеruff, чтобы не ставить их в окружение проекта.
Скажите, что выбрали бы сами и почему. Для нового сервиса разумный дефолт сейчас uv с pyproject.toml и закоммиченным uv.lock, а в CI uv sync --locked, который упадёт, если lock-файл разошёлся с манифестом.
Где спотыкаются
Считают pip freeze > requirements.txt управлением зависимостями. Туда попадает всё подряд, включая dev-инструменты и случайно поставленное, и уже не понять, что проекту нужно напрямую.
Жёстко пинят версии в библиотеке. Точные версии уместны в lock-файле приложения, а пакет для PyPI должен объявлять диапазоны, иначе он конфликтует с зависимостями тех, кто его ставит.
Смешивают conda install и pip install в одном окружении без порядка: conda не знает, что поменял pip, и окружение ломается на следующем обновлении.