Установка основных версий Python на Debian Trixie

Очень, очень часто приходится сталкиваться с необходимостью использования определённой версии Питона, например, для torch, или чего-то специфического.
Использовать conda или Docker в связке с nvidia-container-toolkit и потом настраивать образы вроде nvidia/cuda:13.0.1-runtime-ubuntu22.04 мне ощущается противоестесственно, хотя часто так делал.
Да и в контейнере приходится устанавливать дополнительные пакеты.

Проще и удобней собрать всё на хостовой системе, но при этом не допустить контаминации всей системы посторонними библиотеками и исполняемыми файлами.

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

  • ai - произвольный пользователь, от которого осуществляется компиляция.
  • verpy - группа, которой будет разрешено исполнение.
1
2
3
4
apt install \
    build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev \
    wget curl llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev libffi-dev \
    liblzma-dev libgdbm-dev libnsl-dev libgdbm-compat-dev

mkdir /opt/openssl
mkdir /opt/python
groupadd --gid 42398 verpy
usermod -aG verpy ai

На время установки даём доступ

chown ai:verpy /opt/openssl /opt/python
chmod u=rwX,g=rX,o-rwXx /opt/openssl /opt/python

Переключаемся на пользователя от которого будет производится сборка и установка

su ai
mkdir -p $HOME/src/openssl
cd $HOME/src/openssl

Установка необходимых версий openssl


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# 1.0.2u > python 3.7
wget https://github.com/openssl/openssl/releases/download/OpenSSL_1_0_2u/openssl-1.0.2u.tar.gz
wget https://github.com/openssl/openssl/releases/download/OpenSSL_1_0_2u/openssl-1.0.2u.tar.gz.asc
wget https://github.com/openssl/openssl/releases/download/OpenSSL_1_0_2u/openssl-1.0.2u.tar.gz.sha256
gpg --keyserver keys.gnupg.net --recv-keys 8657ABB260F056B1E5190839D9C4D26D0E604491
gpg --verify openssl-1.0.2u.tar.gz.asc
tar zxf openssl-1.0.2u.tar.gz && cd openssl-1.0.2u
./config --prefix=/opt/openssl/1.0.2u --openssldir=/opt/openssl/1.0.2u/ssl
make -j8
make install_sw

# exec bash - реинициализирует и сбрасывает все переменные окружения, которые могут остаться от предыдущей установки
exec bash
cd $HOME/src/openssl

# 1.1.1w > python 3.9
wget https://github.com/openssl/openssl/releases/download/OpenSSL_1_1_1w/openssl-1.1.1w.tar.gz
wget https://github.com/openssl/openssl/releases/download/OpenSSL_1_1_1w/openssl-1.1.1w.tar.gz.asc
wget https://github.com/openssl/openssl/releases/download/OpenSSL_1_1_1w/openssl-1.1.1w.tar.gz.sha256
gpg --keyserver keys.gnupg.net --recv-keys EFC0A467D613CB83C7ED6D30D894E2CE8B3D79F5
gpg --verify openssl-1.1.1w.tar.gz.asc
tar zxf openssl-1.1.1w.tar.gz && cd openssl-1.1.1w
./config --prefix=/opt/openssl/1.1.1w --openssldir=/opt/openssl/1.1.1w/ssl
make -j8
make install_sw

exec bash
cd $HOME/src/openssl

# 3.0.17 > python 3.10 ; 3.11
wget https://github.com/openssl/openssl/releases/download/openssl-3.0.17/openssl-3.0.17.tar.gz
wget https://github.com/openssl/openssl/releases/download/openssl-3.0.17/openssl-3.0.17.tar.gz.asc
wget https://github.com/openssl/openssl/releases/download/openssl-3.0.17/openssl-3.0.17.tar.gz.sha256
gpg --keyserver keys.gnupg.net --recv-keys BA5473A2B0587B07FB27CF2D216094DFD0CB81EF
gpg --verify openssl-3.0.17.tar.gz.asc
tar zxf openssl-3.0.17.tar.gz && cd openssl-3.0.17
./config --prefix=/opt/openssl/3.0.17 --openssldir=/opt/openssl/3.0.17/ssl
make -j8
make install_sw

exec bash
cd $HOME/src/openssl

# 3.5.4 > python 3.12
wget https://github.com/openssl/openssl/releases/download/openssl-3.5.4/openssl-3.5.4.tar.gz
wget https://github.com/openssl/openssl/releases/download/openssl-3.5.4/openssl-3.5.4.tar.gz.asc
wget https://github.com/openssl/openssl/releases/download/openssl-3.5.4/openssl-3.5.4.tar.gz.sha256
gpg --keyserver keys.gnupg.net --recv-keys BA5473A2B0587B07FB27CF2D216094DFD0CB81EF
gpg --verify openssl-3.5.4.tar.gz.asc
tar zxf openssl-3.5.4.tar.gz && cd openssl-3.5.4
./config --prefix=/opt/openssl/3.5.4 --openssldir=/opt/openssl/3.5.4/ssl
make -j8
make install_sw

exec bash
cd $HOME/src

Установка Python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
mkdir -p $HOME/src/python
cd $HOME/src/python

# python 3.7.17

wget https://www.python.org/ftp/python/3.7.17/Python-3.7.17.tar.xz
wget https://www.python.org/ftp/python/3.7.17/Python-3.7.17.tar.xz.asc
gpg --keyserver keys.gnupg.net --search-keys 0D96DF4D4110E5C43FBFB17F2D347EA6AA65421D
gpg --verify Python-3.7.17.tar.xz.asc
tar xvf Python-3.7.17.tar.xz && cd Python-3.7.17
LDFLAGS="${LDFLAGS} -Wl,-rpath=/opt/openssl/1.1.1w/lib" ./configure --prefix=/opt/python/3.7.17 --enable-optimizations --with-openssl=/opt/openssl/1.1.1w --with-lto --with-computed-gotos --with-system-ffi
make -j8
make test
make install

exec bash
cd $HOME/src/python

# python 3.9.19

wget https://www.python.org/ftp/python/3.9.19/Python-3.9.19.tar.xz
wget https://www.python.org/ftp/python/3.9.19/Python-3.9.19.tar.xz.asc
gpg --keyserver keys.gnupg.net --search-keys E3FF2839C048B25C084DEBE9B26995E310250568
gpg --verify Python-3.9.19.tar.xz.asc
tar xvf Python-3.9.19.tar.xz && cd Python-3.9.19
LDFLAGS="${LDFLAGS} -Wl,-rpath=/opt/openssl/1.1.1w/lib" ./configure --prefix=/opt/python/3.9.19 --enable-optimizations --with-openssl=/opt/openssl/1.1.1w --with-lto --with-computed-gotos --with-system-ffi
make -j8
make test
make install

exec bash
cd $HOME/src/python

# python 3.9.25

wget https://www.python.org/ftp/python/3.9.25/Python-3.9.25.tar.xz
wget https://www.python.org/ftp/python/3.9.25/Python-3.9.25.tar.xz.asc
gpg --keyserver keys.gnupg.net --search-keys E3FF2839C048B25C084DEBE9B26995E310250568
gpg --verify Python-3.9.25.tar.xz.asc
tar xvf Python-3.9.25.tar.xz && cd Python-3.9.25
LDFLAGS="${LDFLAGS} -Wl,-rpath=/opt/openssl/1.1.1w/lib" ./configure --prefix=/opt/python/3.9.25 --enable-optimizations --with-openssl=/opt/openssl/1.1.1w --with-lto --with-computed-gotos --with-system-ffi
make -j8
make test
make install

exec bash
cd $HOME/src/python

# python 3.10.19

wget https://www.python.org/ftp/python/3.10.19/Python-3.10.19.tar.xz
wget https://www.python.org/ftp/python/3.10.19/Python-3.10.19.tar.xz.asc
gpg --keyserver keys.gnupg.net --search-keys CFDCA245B1043CF2A5F97865FFE87404168BD847
gpg --verify Python-3.10.19.tar.xz.asc
tar xvf Python-3.10.19.tar.xz && cd Python-3.10.19
LDFLAGS="${LDFLAGS} -Wl,-rpath=/opt/openssl/3.0.17/lib" ./configure --prefix=/opt/python/3.10.19 --enable-optimizations --with-openssl=/opt/openssl/3.0.17 --with-lto --with-computed-gotos --with-system-ffi
make -j8
make test
make install

exec bash
cd $HOME/src/python

# python 3.11.14

wget https://www.python.org/ftp/python/3.11.14/Python-3.11.14.tar.xz
wget https://www.python.org/ftp/python/3.11.14/Python-3.11.14.tar.xz.asc
gpg --keyserver keys.gnupg.net --search-keys CFDCA245B1043CF2A5F97865FFE87404168BD847
gpg --verify Python-3.11.14.tar.xz.asc
tar xvf Python-3.11.14.tar.xz && cd Python-3.11.14
LDFLAGS="${LDFLAGS} -Wl,-rpath=/opt/openssl/3.0.17/lib" ./configure --prefix=/opt/python/3.11.14 --enable-optimizations --with-openssl=/opt/openssl/3.0.17 --with-lto --with-computed-gotos --with-system-ffi
make -j8
make test
make install

exec bash
cd $HOME/src/python

# python 3.12.12

wget https://www.python.org/ftp/python/3.12.12/Python-3.12.12.tar.xz
wget https://www.python.org/ftp/python/3.12.12/Python-3.12.12.tar.xz.asc
gpg --keyserver keys.gnupg.net --search-keys 7169605F62C751356D054A26A821E680E5FA6305
gpg --verify Python-3.12.12.tar.xz.asc
tar xvf Python-3.12.12.tar.xz && cd Python-3.12.12
LDFLAGS="${LDFLAGS} -Wl,-rpath=/opt/openssl/3.5.4/lib" ./configure --prefix=/opt/python/3.12.12 --enable-optimizations --with-openssl=/opt/openssl/3.5.4 --with-lto --with-computed-gotos
make -j8
make test
make install

exec bash

strip - по вашему желанию

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# [ --strip-all | --strip-unneeded ]
strip --strip-unneeded /opt/python/3.10.19/bin/python3.10
strip --strip-unneeded /opt/python/3.11.14/bin/python3.11
strip --strip-unneeded /opt/python/3.12.12/bin/python3.12
strip --strip-unneeded /opt/python/3.7.17/bin/python3.7
strip --strip-unneeded /opt/python/3.7.17/bin/python3.7m
strip --strip-unneeded /opt/python/3.9.19/bin/python3.9
strip --strip-unneeded /opt/python/3.9.25/bin/python3.9
strip --strip-unneeded /opt/openssl/1.0.2u/bin/openssl
strip --strip-unneeded /opt/openssl/1.1.1w/bin/openssl
strip --strip-unneeded /opt/openssl/3.0.17/bin/openssl
strip --strip-unneeded /opt/openssl/3.5.4/bin/openssl

exit

А теперь забираем права на запись

Всё, Openssl и Питон установлены, доступ на запись можно нужно убрать.
Доступ на чтение, вход в директории и исполнение только для группы verpy.
Все остальные пользователи никак не будут пересекаться с этими пакетами, это не FrankenDebian.

chown -R nobody:verpy /opt/openssl /opt/python
chmod -R u=r,g=rXx,o-rwXx /opt/openssl /opt/python

Линковка всех версий Питона


Под пользователем ai запустим вот такой скрипт:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/bash

if [[ ! -d "$HOME/.local/bin" ]]; then
    mkdir -p $HOME/.local/bin
fi

declare -A dirs=(
  ["3.7.17"]="2to3-3.7 easy_install-3.7 idle3.7 pip3.7 pydoc3.7 python3.7 python3.7m pyvenv-3.7 python3.7m-config"
  ["3.9.25"]="2to3-3.9 idle3.9 pip3.9 pydoc3.9 python3.9 python3.9-config"
  ["3.10.19"]="2to3-3.10 idle3.10 pip3.10 pydoc3.10 python3.10 python3.10-config"
  ["3.11.14"]="2to3-3.11 idle3.11 pip3.11 pydoc3.11 python3.11 python3.11-config"
  ["3.12.12"]="2to3-3.12 idle3.12 pip3.12 pydoc3.12 python3.12 python3.12-config"
)

for dir in "${!dirs[@]}"; do
    printf '%s\n' "$dir"
    bins="${dirs[$dir]}"
    for bin in ${bins}; do
        printf '/opt/python/%s/bin/%s > ~/.local/bin/%s\n' "${dir}" "$bin" "$bin"
        ln -sf /opt/python/${dir}/bin/${bin} $HOME/.local/bin/${bin}
    done
    bins=''
done

Немного тестов

import ssl
ssl.OPENSSL_VERSION
import sys
print(sys.executable)

python3.7

1
2
3
4
5
6
7
8
9
Python 3.7.17 (default, Dec 22 2025, 10:58:22) 
[GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import ssl
>>> ssl.OPENSSL_VERSION
'OpenSSL 1.1.1w  11 Sep 2023'
>>> import sys
>>> print(sys.executable)
/home/ai/.local/bin/python3.7

python3.12

1
2
3
4
5
Python 3.12.12 (main, Dec 22 2025, 12:33:21) [GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import ssl
>>> ssl.OPENSSL_VERSION
'OpenSSL 3.5.4 30 Sep 2025'

Установим torch c python 3.10

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mkdir ~/.torch_env/
python3.10 -m venv ~/.torch_env/
source ~/.torch_env/bin/activate
which pip3
# /home/ai/.torch_env/bin/pip3
which python3.10
# /home/ai/.torch_env/bin/python3.10

python3.10 -m pip install --upgrade pip
pip3 install torch numpy

python3.10
from torch import cuda
print(cuda.get_device_name(cuda.current_device()))
1
2
3
4
5
6
python3.10
Python 3.10.19 (main, Dec 22 2025, 11:39:18) [GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from torch import cuda
>>> print(cuda.get_device_name(cuda.current_device()))
NVIDIA RTX A3000 Laptop GPU

Если некоторые тесты не прошли проверку

Можно продолжить установку а потом пройти этот же тест под тестируемой версией Питон:

1
2
1 test failed:
    test_urllib2

cd ~/src/python/Python-3.7.17/Lib

1
2
3
/opt/python/3.7.17/bin/python3.7 -m test test_ssl
/opt/python/3.7.17/bin/python3.7 -m test test_urllib2
== Tests result: SUCCESS ==