Бегунов ЕгорСистемный администратор, DevOps
  1. Главная
  2. Блог
  3. Scripts

Установка Python на Linux

Содержание

Разработчики принесли сервис, которому нужен Python 3.13. На сервере Debian 12, а там 3.11. Первое желание — поставить новую версию поверх и переключить python3. Так делать не надо.

На системном Python держатся утилиты дистрибутива. На Debian это unattended-upgrades и apt-listchanges, на Ubuntu ещё netplan, cloud-init и add-apt-repository. Подмените /usr/bin/python3, и они начнут падать в самый неподходящий момент. Дальше — как поставить нужную версию рядом с системной и ничего не сломать.

Что понадобится для установки Python на Linux

Требования и подготовка

Debian 12 или 13, Ubuntu 22.04 или 24.04, root или sudo. Сначала смотрим, что уже стоит:

python3 --version
readlink -f "$(command -v python3)"
ls /usr/bin/python3*

Системные версии такие:

  • Debian 12 — 3.11;
  • Debian 13 — 3.13;
  • Ubuntu 22.04 — 3.10;
  • Ubuntu 24.04 — 3.12.

Если системная версия подходит, дальше читать почти не нужно: apt и venv. Если нет, есть три пути.

PPA deadsnakes работает только на Ubuntu. Сборка из исходников работает везде. uv ставит готовые сборки Python без компиляции.

Выбор зависит от того, кто будет обновлять интерпретатор. С PPA обновления приходят через apt. С исходниками и uv обновление — ваша забота. Это стоит решить заранее, а не когда выйдет очередная CVE.

Установка и подготовка среды

Установка пакетов / компонентов

Базовый набор для системного Python:

apt install python3 python3-venv python3-pip python3-dev pipx

python3-dev нужен, когда pip собирает C-расширения. Без него часть пакетов не ставится с ошибкой Python.h: No such file or directory.

Ubuntu и deadsnakes. Самый быстрый путь на Ubuntu LTS. В PPA собраны версии, которых нет в официальном репозитории:

apt install software-properties-common
add-apt-repository ppa:deadsnakes/ppa
apt install python3.13 python3.13-venv python3.13-dev

Интерпретатор встанет как /usr/bin/python3.13. Системный python3 останется прежним. На Debian этот PPA не работает, даже не пробуйте.

Сборка из исходников. Мой вариант для Debian. Сначала зависимости:

apt install build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev \
  libsqlite3-dev libncurses-dev libffi-dev liblzma-dev uuid-dev libgdbm-dev

tk-dev не ставлю, tkinter на сервере не нужен. Дальше качаем исходники и собираем в отдельный префикс:

VER=3.13.7   # актуальную патч-версию смотрите на python.org
cd /usr/local/src
wget https://www.python.org/ftp/python/$VER/Python-$VER.tar.xz
tar xf Python-$VER.tar.xz && cd Python-$VER
./configure --prefix=/opt/python/3.13 --enable-optimizations --with-lto
make -j"$(nproc)" 2>&1 | tee build.log
make altinstall

Сборка с --enable-optimizations идёт заметно дольше обычной, это нормально. Зато интерпретатор получается быстрее.

uv. Если компилировать не хочется, uv скачает готовую сборку. Сам uv ставлю через pipx, бинарник окажется в ~/.local/bin:

pipx install uv
UV_PYTHON_INSTALL_DIR=/opt/uv/python uv python install 3.13

UV_PYTHON_INSTALL_DIR задаю, чтобы интерпретатор лёг в /opt, а не в домашний каталог root. Иначе сервис от другого пользователя его просто не увидит.

Базовая настройка Python на Linux

Основные параметры

Для сборки из исходников важны три флага configure:

  • --prefix — куда ставить. Каждую минорную версию держу в своём каталоге: /opt/python/3.13, /opt/python/3.14.
  • --enable-optimizations — PGO. Сборка дольше, интерпретатор быстрее.
  • --with-lto — оптимизация на этапе линковки, в паре с предыдущим.

И одна команда установки — make altinstall. Она не создаёт ссылки python3 и pip3, только python3.13 и pip3.13. С make install в дефолтный /usr/local новый python3 окажется в PATH раньше системного.

Для pip у меня есть общий конфиг /etc/pip.conf. В нём три вещи: откуда качать, сколько ждать и запрет ставить пакеты мимо venv. Последний параметр, require-virtualenv, спасает от sudo pip install лучше любых регламентов.

Основная конфигурация

Пример конфигурации

Вернёмся к сервису на Debian 12. Python 3.13 собран в /opt/python/3.13, внутренний прокси PyPI поднят на Nexus. Конфиг pip:

# /etc/pip.conf
[global]
index-url = https://nexus.example.local/repository/pypi/simple
timeout = 30
require-virtualenv = true

Сервис получает свой venv на нужной версии. Интерпретатор указываю полным путём, PATH не трогаю:

/opt/python/3.13/bin/python3.13 -m venv /opt/reportsvc/venv
/opt/reportsvc/venv/bin/pip install -r /opt/reportsvc/requirements.txt

Venv запоминает, из какого интерпретатора он создан. Это видно в pyvenv.cfg:

cat /opt/reportsvc/venv/pyvenv.cfg

Дальше сервис запускается через /opt/reportsvc/venv/bin/python, в unit-файле или в cron. Активировать venv для этого не нужно.

Если интерпретатор нужен ещё и людям в консоли, добавляю ссылку с версией в имени:

ln -s /opt/python/3.13/bin/python3.13 /usr/local/bin/python3.13

Именно python3.13, не python3.

Проверка работоспособности

Проверка и тестирование

Сначала новый интерпретатор. Проверяю модули, которые при сборке молча выпадают, если не хватило dev-пакетов:

/opt/python/3.13/bin/python3.13 -c "import ssl, sqlite3, lzma, bz2, zlib, ctypes, readline, curses, dbm.gnu; print(ssl.OPENSSL_VERSION)"

Выдал версию OpenSSL — всё собралось. ModuleNotFoundError — возвращайтесь к списку зависимостей.

Потом pip и доступ к индексу:

/opt/reportsvc/venv/bin/pip download --no-deps -d /tmp/piptest requests

И обязательно системный Python. Он должен остаться нетронутым:

python3 --version
readlink -f /usr/bin/python3

На Ubuntu дополнительно запускаю python3 -c "import apt_pkg". Импорт прошёл — apt-утилиты будут жить.

Флаги, с которыми собран интерпретатор, можно достать из него самого. Удобно, когда через год надо собрать следующую версию так же:

/opt/python/3.13/bin/python3.13 -c "import sysconfig; print(sysconfig.get_config_var('CONFIG_ARGS'))"

Логи и диагностика

При сборке главный лог — вывод make, поэтому выше он пишется в build.log. В конце make печатает модули, которые не собрались или не импортируются. Этот блок легко проскочить в потоке текста:

grep -A5 "necessary bits" build.log
grep -A5 "could not be imported" build.log

Если что-то пошло не так уже на configure, подробности лежат в config.log.

Для pip полезны три команды:

pip config debug           # какие pip.conf найдены и где
pip -v install requests    # подробный лог скачивания и сборки
python3 -m site            # откуда интерпретатор берёт модули

Если непонятно, какой интерпретатор вообще запускается, помогает which -a python3. Она показывает все варианты в порядке PATH.

Безопасность и резервное копирование

С безопасностью у Python на сервере два вопроса: откуда он взялся и кто его обновляет.

Системный Python обновляется вместе с дистрибутивом. Security-патчи приходят через apt, а с unattended-upgrades — вообще без вас. Deadsnakes тоже обновляется через apt, но это сторонний PPA. Патчи там выходят со своей скоростью, и доверяете вы мейнтейнерам PPA.

Со сборкой из исходников все CVE — ваши. Вышел патч-релиз — пересобираете. Подписывайся на рассылку python-announce, иначе про новый релиз узнаёшь от сканера уязвимостей.

Исходники сверяй с подписью на python.org. Для 3.13 это GPG, с 3.14 только Sigstore. Собрать на проде tarball по ссылке из чата — плохая идея, даже если ссылка ведёт куда надо.

По pip правила такие:

  • sudo pip install запрещаем через require-virtualenv и привычку;
  • trusted-host в pip.conf не ставим, для внутреннего CA правим цепочку доверия;
  • зависимости фиксируем с хешами: pip install --require-hashes -r requirements.txt;
  • pip-audit из pipx проверяет установленные пакеты на известные уязвимости.

Теперь резервное копирование. Интерпретаторы и venv в бэкап не кладу. Они пересоздаются, а venv после переноса на другой сервер всё равно не заработает: пути в нём абсолютные. Бэкапить нужно то, из чего всё собирается:

  • requirements.txt каждого сервиса, лучше с хешами;
  • /etc/pip.conf;
  • Bash-скрипт сборки с флагами configure — в git.

Список системных пакетов Python тоже пригодится при переезде:

dpkg -l 'python3*' | awk '/^ii/ {print $2}' > /backup/python-packages.txt

Типичные ошибки

externally-managed-environment. pip install вне venv на Debian 12+ и Ubuntu 23.04+ падает с этой ошибкой. Это PEP 668, защита системного Python от вас. Правильный ответ — venv, pipx или apt install python3-.... --break-system-packages оставьте для контейнеров, которые не жалко.

Переключили python3 через update-alternatives. Классика на Ubuntu. После этого add-apt-repository и часть apt-хуков падают с ModuleNotFoundError: No module named 'apt_pkg'. Модуль собран под системную версию, новая его не видит. Лечится возвратом ссылки на системный интерпретатор.

make install вместо make altinstall. С дефолтным префиксом новый python3 ложится в /usr/local/bin и перекрывает системный в PATH. Скрипты с явным /usr/bin/python3 в shebang живут. Всё, что зовёт просто python3, получает другую версию. Удаляем /usr/local/bin/python3 и pip3, дальше пользуемся altinstall.

Нет модуля ssl. Собрали без libssl-dev, и pip отвечает: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available. Ставим dev-пакет и пересобираем, начиная с configure. Библиотеки он ищет один раз, и повторный make их не заметит.

ensurepip is not available. Ошибка при создании venv: The virtual environment was not created successfully because ensurepip is not available. На Debian и Ubuntu venv вынесен в отдельный пакет. Нужен python3-venv или python3.13-venv для версии из deadsnakes.

Python.h: No such file or directory. pip пытается собрать C-расширение, а заголовков нет. Ставим python3-dev или python3.X-dev под нужную версию. У собранного из исходников Python заголовки уже на месте.

Venv после обновления дистрибутива. Обновили Debian 12 до 13, системный Python стал 3.13. Ссылка venv/bin/python теперь ведёт на 3.13, а пакеты лежат в lib/python3.11. Симптом — внезапный ModuleNotFoundError у сервиса, который вчера работал. Venv пересоздаётся, починить его на месте не выйдет.

Практические рекомендации

Обновление и обслуживание

Патч-релиз, например 3.13.7 → 3.13.8, ставлю в тот же префикс. Собрал, make altinstall, перезапустил сервисы. Venv при этом продолжают работать, минорная версия та же.

Новая минорная версия — новый префикс, /opt/python/3.14. Venv сервисов пересоздаю по одному, с тестами. Старый каталог удаляю, только когда на него никто не ссылается:

grep -l "/opt/python/3.13" /opt/*/venv/pyvenv.cfg

Пустой вывод — можно удалять.

С deadsnakes обновления приходят через apt upgrade, как у системного Python. С uv ставим новую патч-версию через uv python install и пересоздаём venv: путь к интерпретатору в нём содержит полную версию.

Что устарело внутри venv, pip покажет в JSON, его удобно разбирать jq:

/opt/reportsvc/venv/bin/pip list --outdated --format=json | jq -r '.[] | "\(.name) \(.version) -> \(.latest_version)"'

Ещё несколько правил, которые у меня прижились:

  • /usr/bin/python3 не трогаю никогда. Ни ссылками, ни alternatives, ни sudo pip.
  • Одна минорная версия — один каталог в /opt/python. Две сборки в одном префиксе — путь к загадочным ошибкам.
  • Сервисы запускаются через python из своего venv, а не через python3 из PATH.
  • Скрипт сборки лежит в git рядом с остальной автоматизацией. Через год флаги configure никто не вспомнит.
  • Если на сервере есть Docker, вопрос версии часто проще решить образом python:3.13-slim. Но это уже другая статья.

А /usr/bin/python3 на том Debian 12 так и остался 3.11. Сервис про это даже не знает.