Содержание
Разработчики принесли сервис, которому нужен 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. Сервис про это даже не знает.