Блог Stepik про учебу и карьеру

Python и как не быть задушенным его версиями

Практикующий фулстек-разработчик (JS/Python) и автор курсов на Stepik Александр Першин рассказывает, как разработчики управляют версиями Python в проектах. Разберём несколько подходов — от ручной установки и системных инструментов до современных менеджеров окружений — и посмотрим, какие из них действительно удобно использовать в работе.

Практически каждый разработчик хотя бы раз сталкивался с проблемой переключения версий Python. В разных проектах могут использоваться разные версии интерпретатора, и управление ими быстро становится отдельной задачей.

Практически каждый разработчик хотя бы раз сталкивался с проблемой переключения версий Python. В разных проектах могут использоваться разные версии интерпретатора, и управление ими быстро становится отдельной задачей.

Подготовка среды

Для экспериментов я создал тестовую среду самым быстрым способом — запустил официальный образ Python 3.14 в Docker (python:3.14-bookworm).
В образе используется Linux (Debian) и минимальный набор инструментов, необходимых для работы: bash, curl и несколько базовых утилит.
Для удобства используется файл docker-compose.yml.
services:
linux:
image: python:3.14-bookworm
stdin_open: true
tty: true
restart: always

Запуск контейнера

docker compose up -d --build

Найдём имя контейнера (... — сокращение пробелов):

docker container ps
CONTAINER ID ... NAMES
cd487f73dca3 ... linux-linux-1

Теперь подключимся, используя имя и проверим версию
Python:

docker exec -it linux-linux-1 bash
root@cd487f73dca3:/#
root@cd487f73dca3:/# python -V
Python 3.14.2
Всё готово для экспериментов!

Установка Python вручную

Рассмотрим самый базовый сценарий — ручную установку Python. Предположим, нам требуется более старая версия интерпретатора — например, Python 3.8.
curl -O

https://www.python.org/ftp/python/3.8.20/Python-
3.8.20.tgz
Распаковываем:
tar -xvf Python-3.8.20.tgz
Устанавливаем необходимые зависимости и собираем интерпретатор:
apt update && apt install -y build-essential
zlib1g-dev libncurses5-dev libgdbm-dev libnss3-dev
libssl-dev libreadlin e-dev libffi-dev wget
cd Python-3.8.20
./configure --enable-optimizations
make -j $(nproc)
После сборки можно запустить скрипт с использованием новой версии:
root@cd487f73dca3:# ./Python-3.8.20/python main.py
Starting our extremely conservative old program...
Этот подход позволяет использовать нужную версию интерпретатора, но требует ручной настройки и неудобен для регулярной работы.
Кроме того, менять системную версию Python через PATH в Linux-дистрибутивах вроде Debian обычно не рекомендуется — часть системных утилит может зависеть от установленной по умолчанию версии интерпретатора.

Update-alternatives

update-alternatives —полезная утилита, которая позволяет переключаться между версиями чего угодно: начиная от системного редактора по умолчанию и заканчивая версиями Java и Python. Она предполагает ручную установку Python или использование apt, поэтому останавливаться надолго на ней не станем. Всё, что она делает, — это создаёт ссылки на различные интерпретаторы Python и позволяет переключать их под одним псевдонимом — python.

В принципе, эту утилиту можно заменить ручным прописыванием alias python='/путь/к/вашему/python3.10' в файле ~/.bashrc. При использовании update-alternatives, так же как и в предыдущем пункте, важно не заменить стандартный интерпретатор системы другим.

Pyenv

pyenv — это, пожалуй, самый известный инструмент для управления версиями Python. Стоит зайти с вопросом: «Как поменять версию Python?» на любой форум программистов, и с большой долей вероятности вам посоветуют в первую очередь именно его.
Если задать вопрос «как переключить версию Python» на большинстве форумов для разработчиков, pyenv почти всегда будет среди первых рекомендаций.
Установим pyenv:
curl -fsSL https://pyenv.run | bash
Добавим настройки в .bashrc:
export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export
PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init - bash)"
Перезапустим shell:
root@b79964416d4b:/# source ~/.bashrc
Прежде чем выводить список доступных версий Python, установим less
apt install less
Теперь выведем список:
root@b79964416d4b:/# pyenv install -l | less
Выберем Python 3.10.19 и установим:
pyenv install 3.10.19
Теперь создадим новый проект:
root@b79964416d4b:/# mkdir project101
root@b79964416d4b:/# cd project101
Привяжем нужную версию интерпретатора:
root@b79964416d4b:/project101# pyenv local 3.10.19
root@b79964416d4b:/project101# ls
root@b79964416d4b:/project101# ls -la
total 4
drwxr-xr-x. 1 root root 30 Jan 30 15:17 .
drwxr-xr-x. 1 root root 52 Jan 30 15:16 ..

-rw-r--r--. 1 root root 8 Jan 30 15:17 .python-
version
Проверим версию и расположение Python:
root@b79964416d4b:/project101# which python
/root/.pyenv/shims/python
root@b79964416d4b:/project101# python -V
Python 3.10.19
Теперь можно создать main.py и запустить его:
python main.py
Всё довольно просто. Версия Python фиксируется в файле .python-version.

Для pyenv существует плагин pyenv-virtualenv, позволяющий создавать виртуальные окружения.
Установим Python 3.12.0 и создадим новый проект с использованием этого плагина:
root@b79964416d4b:/# pyenv install 3.12.0
root@b79964416d4b:/# pyenv virtualenv 3.12.0 my-project-env
root@b79964416d4b:/# mkdir project102
root@b79964416d4b:/# cd project102
Зафиксируем версию Python:
root@b79964416d4b:/project102# pyenv local my-
project-env

root@b79964416d4b:/project102# python --version
Python 3.12.0
Теперь в файле .python-version вместо версии интерпретатора указано имя виртуального окружения:
root@b79964416d4b:/project102# cat .python-version
my-project-env
Итоги: несмотря на наличие более современных и порой более удобных альтернатив, pyenv является очень популярной. Оставленный ею след в разработке на Python столь велик, что, вероятно, вы и через десятилетия встретите проекты, которые используют pyenv. Разработчику необходимо по меньшей мере знать о её существовании.

Conda

Conda — это пакетный менеджер и менеджер виртуальных окружений. Он позволяет создавать окружения с заранее выбранной версией интерпретатора Python.

Рассмотрим, как установить Conda и создать первое окружение.
Сначала скачиваем установщик:
wget -O anaconda.sh
https://repo.anaconda.com/archive/Anaconda3-
2024.10-1-Linux-x86_64.sh
Запускаем установку:
bash anaconda.sh
Во время установки необходимо принять лицензионные условия — для этого достаточно отвечать yes.
После завершения установки применим изменения для терминала:
source ~/.bashrc
Промпт терминала изменится с:
root@47a21175d2d6:/#
На:
(base) root@47a21175d2d6:/#
Слева в скобках видим псевдоним стандартного интерпретатора, установленного вместе с Cond-ой. Проверим установку:
(base) root@47a21175d2d6:/# conda --version
conda 24.9.2
Теперь посмотрим как Conda работает с проектами. Создадим директорию myproj и виртуальное окружение с версией Python3.8 для него:
(base) root@47a21175d2d6:/# mkdir myproj
(base) root@47a21175d2d6:/# cd myproj/
(base) root@47a21175d2d6:/myproj# conda create -n
venv python=3.8
Выведем доступные окружения:
(venv) root@a977bc34ae43:/myproj# conda env list
# conda environments:
#
base /yes
venv * /yes/envs/venv
Видим, что добавилось новое виртуальное окружение venv.
(base) root@47a21175d2d6:/myproj# conda activate
venv
(venv) root@47a21175d2d6:/myproj# python -V
Python 3.8.20
Стоит заметить, что такое окружение занимает около 1,1 ГБ. Для сравнения: стандартная установка Python занимает примерно 200 МБ.
Однако это объясняется особенностями работы Conda. В отличие от pip, Conda скачивает уже скомпилированные бинарные пакеты. Если библиотеке требуются дополнительные зависимости (например, NumPy зависит от libblas >= 3.8), Conda автоматически устанавливает их и настраивает пути для конкретного окружения.
Такой подход особенно полезен для проектов в области машинного обучения и анализа данных, где используется большое количество системных библиотек.
Conda использует собственный репозиторий пакетов (каналы). По умолчанию используется официальный канал Anaconda, однако при необходимости можно переключиться на открытые репозитории, например conda-forge.
Одно из ключевых преимуществ Conda — возможность управлять не только Python-пакетами, но и внешними зависимостями, например CUDA или системными библиотеками. Благодаря этому проекты можно переносить между системами (например, с Linux на Windows) без ручной настройки зависимостей.
Основной недостаток Conda — скорость работы. Именно поэтому появились альтернативные инструменты, например Mamba, которые реализуют тот же подход, но работают быстрее.

Pixi

После появления ускоренной версии Conda — Mamba — разработчики пошли дальше и создали инструмент Pixi.
Pixi написан на Rust, поэтому работает быстрее многих аналогов.
Установим:
curl -fsSL https://pixi.sh/install.sh | bash
Перезагрузим shell и проверим версию:
root@a977bc34ae43:/# source ~/.bashrc
root@a977bc34ae43:/# pixi --version
pixi 0.63.2
Pixi во многом похож на Conda, но по умолчанию работает с открытым каналом conda-forge. Для управления Python-зависимостями он также использует uv — этот инструмент рассмотрим ниже.

Это работает как резервный сценарий: если нужной библиотеки нет в conda-forge, Pixi обращается к uv и загружает пакет из репозитория PyPI.
Чтобы проверить Pixi на практике, создадим новый проект:
root@a977bc34ae43:/# pixi init my_proj_2
root@a977bc34ae43:/# cd my_proj_2/
Это создаст файл pixi.lock, в котором фиксируются точные версии всех зависимостей.
Теперь установим нужную версию Python и добавим библиотеку для проекта:
pixi add python=3.9
pixi add requests
Это создаст файл pixi.toml, который описывает проект без упоминания строгих версий, в отличии от pixi.lock.
Создадим простенький main.py и запустим его командой:
pixi run python main.py
Hello Pixi!
Отлично: проект запускается без ручного создания виртуального окружения — Pixi берёт это на себя.

UV

Если после Pixi вам кажется, что связка из conda-forge, отдельного менеджера пакетов и uv выглядит избыточной, стоит посмотреть на uv отдельно.
uv — современный менеджер пакетов для Python. Как и Pixi, он написан на Rust, поэтому работает быстро. В отличие от pip, uv позволяет устанавливать конкретные версии Python и сразу создавать виртуальные окружения под выбранную версию.
Установим UV:
curl -LsSf https://astral.sh/uv/install.sh | sh
Перезапустим shell и проверим установку:
root@a977bc34ae43:/# source ~/.bashrc
root@a977bc34ae43:/# uv --version
uv 0.9.27
Теперь создадим новый проект:
root@a977bc34ae43:/# uv init --python 3.8 my_proj_3
cd my_proj_3
Добавим requests:
uv add requests
Аналогично Pixi, точные версии зависимостей сохраняются в лок-файле uv.lock, а структура проекта описывается в pyproject.toml.
Базовый main.py создаётся автоматически, поэтому запустим его:
root@a977bc34ae43:/my_proj_3# uv run main.py
Hello from my-proj-3!
Если хотите глубже разобраться с uv, можно продолжить обучение на курсе «GG Python. UV: управляйте Python-версиями и не только». В нём разбирается, как быстрее управлять зависимостями, окружениями и проектами — без лишней рутины с pip и poetry.

Итоги

В статье мы рассмотрели несколько подходов к управлению версиями Python — от ручной установки до современных менеджеров окружений.
Сегодня разработчики чаще всего используют специализированные инструменты:
  • pyenv — для управления версиями Python в разных проектах;
  • Conda / Pixi — для проектов со сложными зависимостями (например, в машинном обучении);
  • uv — современный и быстрый инструмент для управления зависимостями Python.
Выбор инструмента зависит от задач проекта. Для обычной разработки на Python достаточно лёгких решений вроде pyenv или uv, а для проектов с большим количеством зависимостей удобнее использовать экосистему Conda.