⚠️ Важное предупреждение: Python 3.12 находится в режиме только исправления безопасности (source-only security fixes). Обычные багфиксы и новые возможности закончились с версией 3.12.10. Если вы начинаете новый проект — используйте Python 3.13 или 3.14. Эта инструкция — для поддержки существующего кода.
Предварительные требования
Прежде чем начать, убедитесь, что ваша система готова:
⚠️ ВАЖНО: Проверьте права sudo перед установкой
Если вы не уверены, есть ли у вашего пользователя права администратора, выполните в терминале:
sudo whoami
Что делает:
sudo— выполняет команду от имени суперпользователяwhoami— показывает имя текущего пользователя
Зачем: Проверяет, может ли ваш пользователь выполнять команды с правами root.
✅ Если выводит root — всё в порядке, можете продолжать.
❌ Если выводит is not in the sudoers file — сначала пройдите наше руководство по настройке sudo.
Дополнительные требования:
- Не менее 2-3 ГБ свободного места (исходники, сборка, установка)
- Интернет-соединение для скачивания исходников
- Debian 13, 12 или 11 (любая архитектура, поддерживаемая Debian)
Почему нет пакета python3.12 в Debian?
Debian 13, 12 и 11 не содержат пакет python3.12 в своих стандартных репозиториях. Это связано с тем, что:
- Debian 13 (Trixie) поставляется с Python 3.13
- Debian 12 (Bookworm) поставляется с Python 3.11
- Debian 11 (Bullseye) поставляется с Python 3.9
А Python 3.12 находится в «промежуточном» положении — он уже не новый, но и не старый настолько, чтобы быть в stable-репозиториях.
| Вариант | Статус | Когда использовать |
|---|---|---|
| Сборка из исходников | Работает на всех версиях Debian | Единственный безопасный способ — нужен Python 3.12 |
| APT-пакет из testing/unstable | Не для stable-систем | Не используйте — сломает систему |
| Ubuntu PPA | Не совместим с Debian | Никогда |
Что нужно знать перед установкой (правила безопасности)
Чтобы не повредить Debian, соблюдайте эти правила:
| Правило | Почему это важно |
|---|---|
Запускайте Python командой python3.12 | Системный python3 принадлежит Debian — не трогайте его |
Используйте виртуальные окружения (venv) | pip не будет писать в системные директории Debian |
Сборка использует make altinstall | Устанавливает в /usr/local/python3.12, а не поверх системного |
Не создавайте update-alternatives для python3 | Это заменит системный интерпретатор и сломает ОС |
| Не удаляйте системный Python | Без него перестанут работать APT и половина утилит |
Проверка вашей версии Debian
. /etc/os-release
printf '%s\n' "$PRETTY_NAME"
Что делает: Показывает точное название вашей версии Debian.
python3 --version
Что делает: Показывает версию системного Python.
python3.12 --version 2>/dev/null || echo "Python 3.12 не установлен"
Что делает: Проверяет, не установлен ли уже Python 3.12.
Ожидаемые выводы:
| Debian 13 (Trixie) | Debian 12 (Bookworm) | Debian 11 (Bullseye) |
|---|---|---|
Debian GNU/Linux 13 (trixie) | Debian GNU/Linux 12 (bookworm) | Debian GNU/Linux 11 (bullseye) |
Python 3.13.5 | Python 3.11.2 | Python 3.9.2 |
Python 3.12 не установлен | Python 3.12 не установлен | Python 3.12 не установлен |
Примечание: В таблице «Ожидаемые выводы» для Debian 13 указано Python 3.13.5, но в будущем версия может измениться
Подготовка Debian к сборке Python 3.12
Шаг 1: Обновление системы
sudo apt update
Что делает: Обновляет список доступных пакетов.
Зачем: Всегда обновляйте список пакетов перед установкой нового ПО.
Шаг 2: Установка инструментов сборки и зависимостей
sudo apt install -y ca-certificates wget python3 build-essential zlib1g-dev libncurses-dev \
libgdbm-dev libgdbm-compat-dev libnss3-dev libssl-dev libsqlite3-dev libreadline-dev \
libffi-dev libbz2-dev liblzma-dev uuid-dev libexpat1-dev tk-dev pkg-config make libdb-dev
Что делает: Устанавливает компилятор gcc, заголовочные файлы и библиотеки, необходимые для сборки Python со всеми модулями (SSL, SQLite, сжатие, readline, Tkinter и другие).
Зачем: Без этих пакетов Python соберётся с минимальной функциональностью — многие важные модули (ssl, sqlite3, tkinter) будут отсутствовать.
Шаг 3: Проверка свободного места
df -h "$HOME" /usr/local
Что делает: Показывает свободное место в домашней директории и /usr/local.
Зачем: Сборка требует несколько гигабайт свободного места (~2-3 ГБ).
Создание скрипта-помощника для сборки
Вместо выполнения десятка команд вручную, мы создадим скрипт, который автоматически:
- Найдёт последнюю версию Python 3.12 на python.org (с учётом режима security-fix)
- Скачает исходники и проверит их SHA-256 контрольную сумму
- Соберёт Python с оптимальными настройками
- Установит его в
/usr/local/python3.12черезmake altinstall - Создаст символическую ссылку
/usr/local/bin/python3.12(только если не конфликтует)
Создание файла скрипта
cat <<'EOF' > install-python312-source-debian.sh
#!/usr/bin/env bash
# UnishellRu Python 3.12 source helper
set -euo pipefail
INSTALL_PREFIX="${INSTALL_PREFIX:-/usr/local/python3.12}"
BUILD_DIR="${BUILD_DIR:-$HOME/python3.12-source-build}"
PY312_COMMAND_NAME="${PY312_COMMAND_NAME:-python3.12}"
PY312_BIN="$INSTALL_PREFIX/bin/python3.12"
PY312_FORCE_REBUILD="${PY312_FORCE_REBUILD:-0}"
validate_settings() {
if [[ -z "$INSTALL_PREFIX" || "$INSTALL_PREFIX" != /* ]]; then
printf 'INSTALL_PREFIX must be an absolute path.\n' >&2
exit 1
fi
if [[ -z "$PY312_COMMAND_NAME" || "$PY312_COMMAND_NAME" == */* || "$PY312_COMMAND_NAME" =~ [[:space:]] ]]; then
printf 'PY312_COMMAND_NAME must be a command name, not a path or a value with spaces.\n' >&2
exit 1
fi
}
require_cmd() {
if ! command -v "$1" >/dev/null 2>&1; then
printf 'Missing required command: %s\n' "$1" >&2
exit 1
fi
}
validate_settings
for cmd in python3 awk; do
require_cmd "$cmd"
done
mkdir -p "$BUILD_DIR"
require_link_cmds() {
for cmd in sudo readlink grep mktemp install ln; do
require_cmd "$cmd"
done
}
require_build_cmds() {
for cmd in wget tar make gcc sha256sum nproc tail; do
require_cmd "$cmd"
done
require_link_cmds
}
is_managed_wrapper() {
local path="$1"
local target="$2"
[ -f "$path" ] && grep -Fqx '# UnishellRu Python 3.12 source wrapper' "$path" && grep -Fqx "PY312_SOURCE_TARGET='$target'" "$path"
}
write_command_wrapper() {
local target="$1"
local link="$2"
local tmp_file=""
tmp_file="$(mktemp)"
{
printf '%s\n' '#!/usr/bin/env sh'
printf '%s\n' '# UnishellRu Python 3.12 source wrapper'
printf "PY312_SOURCE_TARGET='%s'\n" "$target"
# shellcheck disable=SC2016
printf '%s\n' 'exec "$PY312_SOURCE_TARGET" "$@"'
} >"$tmp_file"
sudo install -m 0755 "$tmp_file" "$link"
rm -f "$tmp_file"
}
check_command_target_safe() {
local target="$1"
local link="/usr/local/bin/$PY312_COMMAND_NAME"
local existing_path=""
local existing_target=""
if existing_path="$(command -v "$PY312_COMMAND_NAME" 2>/dev/null)"; then
existing_target="$(readlink -f "$existing_path" 2>/dev/null || true)"
if [ -n "$existing_target" ] && [ "$existing_target" != "$target" ] && ! is_managed_wrapper "$existing_path" "$target"; then
printf 'Refusing to shadow existing %s at %s\n' "$PY312_COMMAND_NAME" "$existing_path" >&2
printf 'Set PY312_COMMAND_NAME to a separate name, such as python3.12-source, when another package owns the command.\n' >&2
exit 1
fi
fi
if [ -e "$link" ] && [ ! -L "$link" ] && ! is_managed_wrapper "$link" "$target"; then
printf 'Refusing to overwrite unmanaged path: %s\n' "$link" >&2
exit 1
fi
if [ -L "$link" ]; then
existing_target="$(readlink -f "$link" 2>/dev/null || true)"
if [ -n "$existing_target" ] && [ "$existing_target" != "$target" ]; then
printf 'Refusing to retarget existing symlink: %s\n' "$link" >&2
exit 1
fi
fi
}
install_command_link() {
local target="$1"
local link="/usr/local/bin/$PY312_COMMAND_NAME"
check_command_target_safe "$target"
if [ "$PY312_COMMAND_NAME" = "python3.12" ]; then
sudo ln -sfn "$target" "$link"
else
write_command_wrapper "$target" "$link"
fi
}
fetch_release_metadata() {
python3 - <<'PY'
import gzip
import re
from urllib.request import urlopen
release_html = urlopen("https://www.python.org/downloads/latest/python3.12/", timeout=20).read()
if release_html.startswith(b"\x1f\x8b"):
release_html = gzip.decompress(release_html)
release_html = release_html.decode("utf-8")
version_match = re.search(r'<h1 class="page-title">Python (3\.12\.\d+)</h1>', release_html)
if not version_match:
raise SystemExit("Could not find the latest Python 3.12 release version")
version = version_match.group(1)
row = re.search(
r'<tr>\s*<td><a href="(?P<url>[^"]*Python-' + re.escape(version) + r'\.tar\.xz)">XZ compressed source tarball</a></td>.*?<code class="checksum">(?P<checksum>.*?)</code>',
release_html,
re.S,
)
if not row:
raise SystemExit("Could not find the XZ source tarball checksum")
checksum_text = re.sub(r"<[^>]+>", "", row.group("checksum"))
sha256 = re.sub(r"[^0-9a-f]", "", checksum_text)
if len(sha256) != 64:
raise SystemExit(f"Unexpected SHA-256 checksum length: {len(sha256)}")
print(f"PY312_VERSION='{version}'")
print(f"PY312_URL='{row.group('url')}'")
print(f"PY312_SHA256='{sha256}'")
PY
}
run_logged() {
local label="$1"
shift
local log_file="$BUILD_DIR/${label}-${PY312_VERSION}.log"
if "$@" >"$log_file" 2>&1; then
printf '%s complete; see %s\n' "$label" "${label}-${PY312_VERSION}.log"
else
printf '%s failed; last log lines:\n' "$label" >&2
tail -n 50 "$log_file" >&2 || true
exit 1
fi
}
metadata_file="$BUILD_DIR/python312-release.env"
fetch_release_metadata >"$metadata_file"
# shellcheck source=/dev/null
. "$metadata_file"
printf 'Using Python %s\n' "$PY312_VERSION"
if [ -x "$PY312_BIN" ]; then
current_version="$("$PY312_BIN" --version | awk '{print $2}')"
if [ "$current_version" = "$PY312_VERSION" ] && [ "$PY312_FORCE_REBUILD" != "1" ]; then
require_link_cmds
install_command_link "$PY312_BIN"
printf 'Python %s already installed at %s\n' "$current_version" "$PY312_BIN"
exit 0
fi
fi
require_build_cmds
check_command_target_safe "$PY312_BIN"
cd "$BUILD_DIR"
archive="Python-${PY312_VERSION}.tar.xz"
srcdir="Python-${PY312_VERSION}"
sudo rm -rf -- "$srcdir"
rm -f -- "$archive"
wget -q -O "$archive" "$PY312_URL"
printf '%s %s\n' "$PY312_SHA256" "$archive" | sha256sum -c -
tar -xf "$archive"
cd "$srcdir"
configure_args=(--with-ensurepip=install "--prefix=$INSTALL_PREFIX")
if [ -n "${PY312_CONFIGURE_EXTRA:-}" ]; then
# shellcheck disable=SC2206
extra_args=($PY312_CONFIGURE_EXTRA)
configure_args+=("${extra_args[@]}")
fi
run_logged configure ./configure "${configure_args[@]}"
run_logged make make -j"$(nproc)"
run_logged altinstall sudo make altinstall
printf '%s\n' "$INSTALL_PREFIX/lib" | sudo tee "/etc/ld.so.conf.d/${PY312_COMMAND_NAME}.conf" >/dev/null
sudo ldconfig
if [ -x "$PY312_BIN" ]; then
install_command_link "$PY312_BIN"
"$PY312_BIN" --version
cd "$BUILD_DIR"
sudo rm -rf -- "$srcdir"
rm -f -- "$archive"
else
printf 'Build completed, but %s was not found.\n' "$PY312_BIN" >&2
exit 1
fi
EOF
Что делает этот скрипт (обзорно):
- Проверяет наличие всех необходимых команд
- Скачивает с python.org страницу последнего релиза Python 3.12 и SHA-256 контрольную сумму
- Скачивает исходники и проверяет их целостность
- Конфигурирует сборку с поддержкой всех модулей
- Собирает Python, используя все ядра процессора (
-j"$(nproc)") - Устанавливает через
make altinstall(безопасная установка в отдельный префикс) - Создаёт символическую ссылку в
/usr/local/bin(с проверкой конфликтов)
chmod +x install-python312-source-debian.sh
Что делает: Делает скрипт исполняемым.
Запуск сборки Python 3.12
./install-python312-source-debian.sh
Что делает: Запускает скрипт сборки.
Ожидаемый вывод:
Using Python 3.12.13
Python-3.12.13.tar.xz: OK
configure complete; see configure-3.12.13.log
make complete; see make-3.12.13.log
altinstall complete; see altinstall-3.12.13.log
Python 3.12.13
Что означают ключевые строки:
Using Python 3.12.13— определена версия для установкиPython-3.12.13.tar.xz: OK— контрольная сумма совпала, архив не повреждёнPython 3.12.13— финальный вывод установленного интерпретатора
⚠️ Если видите FAILED или mismatch — не продолжайте. Это означает, что скачанный архив повреждён или подменён.
Сколько это займёт: На современном компьютере сборка занимает 5-15 минут, в зависимости от количества ядер процессора.
Установка скрипта обновления (после успешной сборки)
sudo install -m 0755 install-python312-source-debian.sh /usr/local/bin/update-python312-source
Что делает: Копирует скрипт в /usr/local/bin с правами на исполнение, чтобы можно было обновлять Python одной командой.
command -v update-python312-source
Ожидаемый вывод: /usr/local/bin/update-python312-source
Проверка установки Python 3.12
Проверка версии
python3.12 --version
Ожидаемый вывод: Python 3.12.x (где x — последняя security-версия с python.org).
Проверка важных модулей
python3.12 -c "import ssl, sqlite3, bz2, lzma, zlib, ctypes, readline, tkinter, dbm.gnu; print('Python 3.12 готов на Debian')"
Что делает: Импортирует ключевые модули стандартной библиотеки.
Ожидаемый вывод: Python 3.12 готов на Debian
Если получили ошибку импорта — значит, не установлен соответствующий -dev пакет. Установите недостающий пакет и пересоберите Python (см. раздел «Решение проблем»).
Проверка pip
python3.12 -m pip --version
Что делает: Показывает версию pip, установленного для Python 3.12.
Ожидаемый вывод: pip 25.x from /usr/local/python3.12/lib/python3.12/site-packages/pip (python 3.12)
Использование Python 3.12 через виртуальное окружение
⚠️ Важнейшее правило: Никогда не устанавливайте пакеты через pip глобально для python3.12. Всегда используйте виртуальные окружения (venv).
Создание виртуального окружения
mkdir -p "$HOME/venvs"
Что делает: Создаёт директорию для всех виртуальных окружений (если её нет).
python3.12 -m venv "$HOME/venvs/py312"
Что делает: Создаёт виртуальное окружение с Python 3.12.
Зачем: Внутри venv можно устанавливать любые пакеты через pip без риска повредить систему.
Активация виртуального окружения
source "$HOME/venvs/py312/bin/activate"
Что делает: Активирует виртуальное окружение в текущем сеансе терминала.
Ожидаемое изменение приглашения: (py312) user@debian:~$
Установка пакетов внутри venv
python -m pip install --upgrade pip
python -m pip install requests
Что делает: Обновляет pip в окружении и устанавливает пакет requests.
Зачем: python внутри venv ссылается на Python 3.12, а не на системный.
Проверка, что вы внутри venv
which python
Ожидаемый вывод: /home/username/venvs/py312/bin/python
Деактивация виртуального окружения
deactivate
Что делает: Возвращает терминал к системному Python.
Обновление Python 3.12
Так как Python собран из исходников, он не обновляется через APT. При выходе новой security-версии 3.12.x выполните:
update-python312-source
Что делает: Проверяет последнюю версию на python.org и пересобирает, если нужно.
Если новая версия не требуется, скрипт выведет:
Using Python 3.12.13
Python 3.12.13 already installed at /usr/local/python3.12/bin/python3.12
Принудительная пересборка (если менялись зависимости или флаги):
PY312_FORCE_REBUILD=1 update-python312-source
Удаление Python 3.12
Если Python 3.12 больше не нужен:
⚠️ Перед удалением: Убедитесь, что ни один проект не использует виртуальные окружения с этим Python.
# Удаление символической ссылки
sudo rm -f /usr/local/bin/python3.12
# Удаление скрипта обновления
sudo rm -f /usr/local/bin/update-python312-source
# Удаление самой установки Python
sudo rm -rf /usr/local/python3.12
# Удаление конфигурации динамического линковщика
sudo rm -f /etc/ld.so.conf.d/python3.12.conf
sudo ldconfig
# Удаление директории со сборкой
sudo rm -rf "$HOME/python3.12-source-build"
# Удаление виртуального окружения (если создавали)
rm -rf "$HOME/venvs/py312"
# Очистка кэша команд
hash -r
Проверка удаления:
command -v python3.12 || echo "python3.12 удалён"
python3 --version
Решение типичных проблем
8.1 Ошибка: APT не может найти пакет python3.12
Симптом: sudo apt install python3.12 выдаёт E: Unable to locate package python3.12.
Причина: В Debian 13, 12 и 11 нет пакета python3.12 в официальных репозиториях. Это ожидаемое поведение.
Решение: Используйте сборку из исходников (описанную выше). Не добавляйте testing/unstable или Ubuntu PPA.
8.2 Ошибка: Скрипт отказывается создавать python3.12 (shadow)
Симптом: Скрипт выводит Refusing to shadow existing python3.12 at /usr/bin/python3.12.
Причина: Команда python3.12 уже существует (например, вы установили её из другого источника).
Решение: Используйте side-установку с другим именем:
INSTALL_PREFIX=/usr/local/python3.12-side \
PY312_COMMAND_NAME=python3.12-side \
./install-python312-source-debian.sh
8.3 Ошибка: pip не работает (ModuleNotFoundError)
Симптом: python3.12 -m pip --version выдаёт ModuleNotFoundError: No module named 'pip'.
Причина: Скрипт собирал Python без флага --with-ensurepip=install (но в нашем скрипте он есть).
Решение: Убедитесь, что pip существует:
/usr/local/python3.12/bin/pip3.12 --version
Если нет — пересоберите с флагом:
PY312_FORCE_REBUILD=1 update-python312-source
8.4 Ошибка: Missing modules после сборки (_ssl, _sqlite3 и др.)
Симптом: При импорте модуля (import ssl) получаете ModuleNotFoundError.
Причина: Не был установлен соответствующий -dev пакет до сборки.
Пошаговое решение:
Шаг 1: Установите недостающие заголовочные файлы:
sudo apt install libssl-dev libsqlite3-dev libbz2-dev liblzma-dev tk-dev -y
Шаг 2: Принудительно пересоберите Python:
PY312_FORCE_REBUILD=1 update-python312-source
Шаг 3: Проверьте, что модуль теперь импортируется:
python3.12 -c "import ssl; print('SSL OK')"
8.5 Ошибка: Недостаточно памяти для сборки
Симптом: Процесс сборки прерывается с ошибкой «Cannot allocate memory» или «Killed».
Причина: На сервере меньше 2 ГБ ОЗУ, и процесс компиляции убивает OOM Killer.
Пошаговое решение:
Шаг 1: Проверьте доступную память:
free -h
Шаг 2: Добавьте swap (если нет или мало):
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
Шаг 3: Сделайте swap постоянным (добавьте в /etc/fstab):
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
8.6 Ошибка: Debian Tools сломались после изменений Python
Симптом: APT или другие утилиты выдают ошибки, связанные с Python.
Причина: Был заменён или удалён системный /usr/bin/python3.
Пошаговое решение:
Шаг 1: Проверьте, куда указывает системный Python:
ls -l /usr/bin/python3
dpkg -S /usr/bin/python3
Что ищем: Должна быть ссылка на /usr/bin/python3.x (например, /usr/bin/python3.11).
Шаг 2: Переустановите системные пакеты Python:
sudo apt install --reinstall python3 python3-minimal python3-apt -y
Шаг 3: Проверьте:
python3 --version
sudo apt update
Чек-лист: что проверить после установки
- [ ]
sudo whoamiвыводитroot - [ ]
python3 --versionпоказывает версию системного Python (3.13 на Trixie, 3.11 на Bookworm, 3.9 на Bullseye) - [ ]
python3.12 --versionпоказываетPython 3.12.x - [ ]
python3.12 -c "import ssl, sqlite3, bz2, lzma, zlib"выполняется без ошибок - [ ]
python3.12 -m pip --versionпоказывает pip из/usr/local/python3.12 - [ ]
command -v update-python312-sourceпоказывает/usr/local/bin/update-python312-source - [ ] Виртуальное окружение создаётся:
python3.12 -m venv /tmp/test-venv - [ ] Внутри venv работает
pip install
Заключение
Python 3.12 успешно установлен на Debian в отдельный префикс /usr/local/python3.12. Системный Python остался нетронутым. Теперь вы можете:
- Поддерживать легаси-проекты, которые ещё не перешли на Python 3.13 или 3.14
- Использовать виртуальные окружения для изоляции зависимостей
- Обновлять Python одной командой
update-python312-sourceпри выходе security-исправлений
Что дальше:
- Изучите список изменений в Python 3.12 (особенно если переходите с 3.11)
- Для новых проектов используйте Python 3.13 по нашей инструкции или Python 3.14 по инструкции для Python 3.14
- Установите инструменты для разработки на Python для более комфортной работы
💡 Важно: Python 3.12 получает только исправления безопасности. Не ждите новых функций. Если ваш проект позволяет — планируйте переход на Python 3.13 или 3.14. Если нет — эта установка обеспечит безопасную и стабильную среду для вашего легаси-кода.