Python 3.8 reached end-of-life in October 2024, but plenty of legacy projects still depend on it. Ubuntu 26.04, 24.04, and 22.04 ship newer default interpreters (Python 3.14, 3.12, and 3.10), so install Python 3.8 as a side-by-side interpreter rather than replacing Ubuntu’s system Python.
The Deadsnakes PPA now provides Python 3.8 packages for all three supported Ubuntu LTS releases, while source compilation remains useful for custom prefixes or offline rebuilds. Use virtual environments to keep legacy dependencies contained on a modern Ubuntu system.
Install Python 3.8 on Ubuntu
Ubuntu’s default repositories do not provide the python3.8 package on Ubuntu 26.04, 24.04, or 22.04, so apt install python3.8 fails until you add a third-party source or compile Python 3.8 from source. Most users should use the Deadsnakes PPA because it keeps the interpreter in APT without changing /usr/bin/python3.
| Method | Channel | Branch | Updates | Best For |
|---|---|---|---|---|
| APT (Deadsnakes PPA) | Launchpad PPA | Python 3.8.20 packages for 26.04, 24.04, and 22.04 | APT-managed community packages; no guaranteed security SLA | Most Ubuntu systems that need packaged Python 3.8 without replacing the default interpreter |
| Source Compilation | python.org | Python 3.8.20 final source release | Manual rebuilds only | Air-gapped hosts, custom prefixes, or workflows that cannot use a PPA |
Recommendation: Use the Deadsnakes PPA on Ubuntu 26.04, 24.04, or 22.04 for simpler package management, then use source builds only when you need tighter control over the build or cannot use third-party APT sources.
These instructions cover Ubuntu 26.04 LTS, 24.04 LTS, and 22.04 LTS. The Deadsnakes PPA currently publishes Python 3.8 packages for each release; compile from source only when your environment needs a custom build or cannot use that repository.
Update Ubuntu Before Installing Python 3.8
Refresh the APT package index first so dependency checks and repository metadata are current before you add the Deadsnakes PPA or install build tools.
sudo apt update
APT should finish by reading package lists without errors. The mirror lines vary by release and region, but the final line should confirm the package lists were read successfully:
Hit:1 http://archive.ubuntu.com/ubuntu noble InRelease Hit:2 http://security.ubuntu.com/ubuntu noble-security InRelease Reading package lists... Done
Commands that install packages or change system directories use
sudo. If your account is not in the sudoers file yet, use the root account or follow the guide on adding a user to sudoers on Ubuntu before continuing.
Check Python 3.8 Availability in Ubuntu Repositories
Before adding the Deadsnakes PPA or compiling from source, confirm that Ubuntu’s default repositories do not provide Python 3.8. This answers the common errors Package 'python3.8' has no installation candidate and Unable to locate package python3.8.
apt-cache policy python3.8
Expected output on a system that has not added the Deadsnakes PPA yet:
python3.8: Installed: (none) Candidate: (none) Version table:
If you already added the Deadsnakes PPA, this command will show a candidate version instead of (none). On a clean Ubuntu 26.04, 24.04, or 22.04 install, no candidate appears until you use a third-party source.
E: Package 'python3.8' has no installation candidate
- Ubuntu archives no longer ship
python3.8:https://packages.ubuntu.com/jammy/python3.8,https://packages.ubuntu.com/noble/python3.8, andhttps://packages.ubuntu.com/resolute/python3.8return “No such package.” - Deadsnakes includes a “no guaranteed updates” disclaimer: use it only for controlled legacy workloads, and monitor CVEs yourself if the application is exposed to untrusted input.
- Modern ecosystems already dropped Python 3.8: Django 5.0 and NumPy 2.0 no longer support it, so expect more package installs and upgrades to fail over time.
Python 3.8 no longer receives upstream security patches. Install it only for legacy compatibility, keep workloads isolated (virtual environments or containers), and plan migrations to supported versions. Ubuntu 26.04 ships Python 3.14, Ubuntu 24.04 ships Python 3.12, and Ubuntu 22.04 ships Python 3.10.
Install Python 3.8 from the Deadsnakes PPA
Add the Deadsnakes PPA for Python 3.8
If add-apt-repository is missing (minimal, WSL, or container installs), install software-properties-common first:
sudo apt install software-properties-common
The Deadsnakes PPA publishes Python 3.8 packages for Ubuntu 26.04, 24.04, and 22.04. This guide targets Ubuntu; Ubuntu-based distributions such as Linux Mint 22 may block this PPA by default.
Deadsnakes is a community-maintained Launchpad PPA that provides non-default Python releases for Ubuntu, including Python 3.8 on supported LTS versions. Add the “deadsnakes” team PPA with this command. The helper configures the repository and signing key for your Ubuntu release:
The Launchpad package metadata currently shows Python 3.8.20 builds for Ubuntu 26.04, 24.04, and 22.04, so each supported Ubuntu LTS release can install python3.8 directly without manual compilation.
Launchpad also reiterates the Deadsnakes disclaimer: there is no guarantee of timely security fixes, so production teams must monitor CVEs and be ready to recompile or sandbox workloads if a vulnerability appears before patched packages land.
sudo add-apt-repository ppa:deadsnakes/ppa -y
The -y flag auto-accepts the repository prompt, which is useful for scripted installs but skips the interactive confirmation.
Optional: Configure APT Pinning for Deadsnakes Python 3.8 Packages
This step is optional. If you only plan to install python3.8 and a few explicit python3.8-* packages, you can skip pinning and continue to the APT update step. Use pinning on shared systems or long-lived servers where you want to prevent unrelated Deadsnakes packages from being preferred accidentally.
cat <<EOF | sudo tee /etc/apt/preferences.d/python3.8.pref
Package: *
Pin: release o=LP-PPA-deadsnakes
Pin-Priority: 100
Package: python3.8*
Pin: release o=LP-PPA-deadsnakes
Pin-Priority: 700
EOF
The tee command writes the configuration file with root permissions because standard shell redirection (>) does not inherit sudo privileges. The rule uses the verified Deadsnakes APT Origin value LP-PPA-deadsnakes, keeping unrelated Deadsnakes packages at lower priority while allowing python3.8* packages to install from the PPA.
Update APT After Adding the Python 3.8 PPA
Refresh APT after adding the PPA so Ubuntu can see the new Python 3.8 packages:
sudo apt update
A successful refresh includes the Deadsnakes repository line for your release:
Hit:1 http://archive.ubuntu.com/ubuntu noble InRelease Hit:2 http://security.ubuntu.com/ubuntu noble-security InRelease Hit:3 https://ppa.launchpadcontent.net/deadsnakes/ppa/ubuntu noble InRelease Reading package lists... Done
Verify the Deadsnakes PPA Provides Python 3.8
Before installing Python 3.8, verify that the Deadsnakes PPA is active and providing the package. This confirms the repository was added successfully:
apt-cache policy python3.8
Expected output on Ubuntu 26.04:
python3.8:
Installed: (none)
Candidate: 3.8.20-1+resolute1
Version table:
3.8.20-1+resolute1 700
100 https://ppa.launchpadcontent.net/deadsnakes/ppa/ubuntu resolute/main amd64 Packages
Expected output on Ubuntu 24.04:
python3.8:
Installed: (none)
Candidate: 3.8.20-1+noble1
Version table:
3.8.20-1+noble1 700
100 https://ppa.launchpadcontent.net/deadsnakes/ppa/ubuntu noble/main amd64 Packages
Expected output on Ubuntu 22.04:
python3.8:
Installed: (none)
Candidate: 3.8.20-1+jammy1
Version table:
3.8.20-1+jammy1 700
100 https://ppa.launchpadcontent.net/deadsnakes/ppa/ubuntu jammy/main amd64 Packages
The output confirms Python 3.8.20 is available from the PPA. If you skipped pinning, the priority will show 500 instead of 700. The version number may differ if Deadsnakes republishes the package, and the distribution name matches your Ubuntu version.
Install Python 3.8 via APT Command
With the PPA active, install Python 3.8 on Ubuntu 26.04, 24.04, or 22.04 with APT:
sudo apt install python3.8
Verify Python 3.8 Installation
After installation completes, verify Python 3.8 installed correctly by checking the version string:
python3.8 --version
This command displays the installed Python 3.8 version, confirming the installation succeeded:
Python 3.8.20
Verify that the SSL module compiled correctly, which is critical for OpenSSL 3 compatibility on Ubuntu 22.04 and newer:
python3.8 -c "import ssl, sqlite3, bz2; print('Core modules OK')"
Expected output confirming all core modules loaded successfully:
Core modules OK
If the SSL import fails, use the “Fix Python 3.8 OpenSSL Module Build Failures” troubleshooting section for diagnosis and repair steps.
Install Optional Python 3.8 Packages (venv, dev, distutils)
Install these optional packages only when your workflow needs them. The most commonly requested extras are python3.8-venv, python3.8-dev, and python3.8-distutils.
| Package | Why Install It |
|---|---|
| python3.8-dbg | Provides debugging symbols so you can trace crashes or attach gdb to Python processes |
| python3.8-dev | Installs headers for compiling native extensions such as uvloop or psycopg2 |
| python3.8-venv | Enables the built-in venv module so you can isolate dependencies per project |
| python3.8-distutils | Provides the legacy Distutils packaging tools still used by some build scripts |
| python3.8-lib2to3 | Installs the modernization tool used to port legacy Python 2 code |
| python3.8-gdbm | Adds GNU dbm bindings so your apps can use dbm.gnu databases |
| python3.8-tk | Ships Tk bindings (Tkinter) for GUI applications |
Installing python3.8-venv pulls in python3.8-distutils and python3.8-lib2to3 automatically, so you may already have those packages once venv is installed.
Install optional modules individually as needed:
sudo apt install python3.8-dbg
sudo apt install python3.8-dev
sudo apt install python3.8-venv
sudo apt install python3.8-distutils
sudo apt install python3.8-lib2to3
sudo apt install python3.8-gdbm
sudo apt install python3.8-tk
Only install legacy components like python3.8-distutils or python3.8-lib2to3 when a project explicitly requires them; modern packaging tools favor pip, setuptools, and pyproject.toml-based builds.
Install whichever modules you need in a single apt command to save time:
sudo apt install python3.8-venv python3.8-dev python3.8-tk
Update Deadsnakes Python 3.8 Packages on Ubuntu
When updates are available, upgrade only the Python 3.8 packages you installed to avoid pulling in unrelated PPA packages:
sudo apt install --only-upgrade python3.8 python3.8-venv python3.8-dev
Add or remove python3.8-* packages in the command based on what you installed.
Compile Python 3.8 from Source on Ubuntu
Download Python 3.8 Source Code
Visit the official Python download page to confirm the final Python 3.8 source release. If curl is missing, install it first:
sudo apt install curl
Now download the Python 3.8 source archive:
curl -fsSLO https://www.python.org/ftp/python/3.8.20/Python-3.8.20.tar.xz
This command runs quietly on success because of the -sS flags, so no terminal output is expected unless curl hits an error.
(no output)
The -f flag fails on HTTP errors, -sS keeps output quiet while still showing errors, -L follows redirects, and -O saves the file with its original name.
Optional but recommended: verify the source archive with the matching OpenPGP signature before extracting it. Python.org lists the Python 3.8 source signing key on its OpenPGP verification page:
sudo apt install gnupg
curl -fsSLO https://www.python.org/ftp/python/3.8.20/Python-3.8.20.tar.xz.asc
gpg --keyserver hkps://keyserver.ubuntu.com --recv-keys E3FF2839C048B25C084DEBE9B26995E310250568
gpg --verify Python-3.8.20.tar.xz.asc Python-3.8.20.tar.xz
A successful verification reports a good signature from the Python 3.8 release manager key. The trust warning is normal when you have not personally certified that OpenPGP key.
Python 3.8.20 is the final release of the Python 3.8 series. No further updates are planned, so the version numbers here will remain current. If you are upgrading from an older 3.8.x build, download 3.8.20 to gain OpenSSL 3.x compatibility.
If you need an exact older patch release such as Python 3.8.10 for a legacy test matrix, download that source release explicitly from python.org and compile it in a dedicated prefix. On current Ubuntu LTS releases, Python 3.8.20 is the safer 3.8 build because it includes the final security fixes and works with OpenSSL 3.x.
Most Ubuntu installations already include xz-utils. On minimal systems, install it before extracting the .tar.xz archive:
sudo apt install xz-utils
After downloading the Python archive, extract it using tar:
tar -xf Python-3.8.20.tar.xz
Install Python 3.8 Build Dependencies on Ubuntu
Before compiling Python from source, install the build dependencies. The build-essential package provides GCC and core compilation tools, while the development libraries supply headers for SSL, compression, and database support:
sudo apt install build-essential zlib1g-dev libncurses-dev libgdbm-dev libnss3-dev libssl-dev libsqlite3-dev libreadline-dev libffi-dev curl libbz2-dev liblzma-dev pkg-config make xz-utils
These package names are available on Ubuntu 26.04 LTS, 24.04 LTS, and 22.04 LTS.
Python 3.8.16+ is required on Ubuntu 26.04, 24.04, and 22.04 because these releases ship OpenSSL 3 (
libssl3). Earlier 3.8.x builds expect OpenSSL 1.1.1 and fail to build thesslmodule, so use Python 3.8.20 for source builds on current Ubuntu LTS releases.
Configure the Python 3.8 Source Build
Navigate to the extracted source directory:
cd Python-3.8.20/
Run the ./configure command with --enable-shared so the build installs libpython3.8.so for embedded applications and the linker-cache step:
./configure --enable-shared
--enable-shared builds libpython3.8.so as a shared library, required by applications that embed the Python interpreter and by the ldconfig step. If you intentionally want profile-guided optimization, add --enable-optimizations after testing the longer build on the target host.
Expected output near the end of a successful configure run:
checking whether compiling and linking against OpenSSL works... yes checking for X509_VERIFY_PARAM_set1_host in libssl... yes configure: creating ./config.status creating Makefile
Compile Python 3.8
After configuring the build environment, compile Python using the make command. To significantly speed up compilation, use the -j flag to enable parallel builds across multiple CPU cores:
make -j $(nproc)
The $(nproc) command automatically detects your available CPU cores and runs that many parallel jobs, significantly speeding up compilation.
A successful build finishes by creating Python 3.8 helper scripts and leaving the source tree:
renaming build/scripts-3.8/pydoc3 to build/scripts-3.8/pydoc3.8 renaming build/scripts-3.8/idle3 to build/scripts-3.8/idle3.8 renaming build/scripts-3.8/2to3 to build/scripts-3.8/2to3-3.8 make[1]: Leaving directory '.../Python-3.8.20'
Install Python 3.8 Binaries
Install the compiled binaries with altinstall instead of install to avoid overwriting Ubuntu’s /usr/bin/python3 symlink:
sudo make altinstall
The final lines should show the bundled ensurepip step finishing successfully:
Processing .../setuptools-56.0.0-py3-none-any.whl Processing .../pip-23.0.1-py3-none-any.whl Installing collected packages: setuptools, pip Successfully installed pip-23.0.1 setuptools-56.0.0
After installation, update the dynamic linker cache so the system can locate the Python 3.8 shared library (libpython3.8.so) when running Python or importing extension modules. If you compiled with the default prefix (--prefix=/usr/local), run:
sudo ldconfig /usr/local/lib
The command produces no output on success. Verify the library is now registered by checking the linker cache:
ldconfig -p | grep python3.8
Expected output confirming the shared library is findable:
libpython3.8.so.1.0 (libc6,x86-64) => /usr/local/lib/libpython3.8.so.1.0 libpython3.8.so (libc6,x86-64) => /usr/local/lib/libpython3.8.so
When you compiled with a custom prefix (for example ./configure --prefix=/opt/python3.8), provide that path explicitly:
sudo ldconfig /opt/python3.8/lib
Verify Python 3.8 Installation
After configuring the dynamic linker, confirm the source-compiled Python 3.8 installation succeeded and the version matches your downloaded release:
python3.8 --version
Expected output:
Python 3.8.20
Verify that critical modules like SSL compiled correctly, since missing development headers during compilation cause silent module failures. Run this test to confirm OpenSSL 3 compatibility:
python3.8 -c "import ssl; print('SSL module OK'); print(ssl.OPENSSL_VERSION)"
Expected output (the OpenSSL version string varies by Ubuntu release):
SSL module OK OpenSSL 3.x.x ...
Your OpenSSL version string differs by release. The important confirmation is seeing OpenSSL 3.x rather than OpenSSL 1.1.1, which would indicate an incompatible build on current Ubuntu LTS releases.
Update a Source-Built Python 3.8 Installation
Source builds do not update themselves. Python 3.8.20 is the final release of the Python 3.8 series, so no future upstream point releases are expected. Rebuild only when you previously installed an older 3.8.x release, need to change build flags, or need to reinstall into a different prefix.
Check your installed version first:
python3.8 --version
If the command reports an older 3.8.x release, rebuild from the final source release:
mkdir -p "$HOME/python3.8-build"
cd "$HOME/python3.8-build"
rm -rf Python-3.8.20 Python-3.8.20.tar.xz
curl -fsSLO https://www.python.org/ftp/python/3.8.20/Python-3.8.20.tar.xz
tar -xf Python-3.8.20.tar.xz
cd Python-3.8.20
./configure --enable-shared
make -j "$(nproc)"
sudo make altinstall
sudo ldconfig /usr/local/lib
python3.8 --version
python3.8 -c "import ssl; print('SSL:', ssl.OPENSSL_VERSION)"
When the rebuild completes successfully, the final checks should show Python 3.8.20 and an OpenSSL 3.x version:
Python 3.8.20 SSL: OpenSSL 3.x.x ...
If the SSL import fails, verify that libssl-dev was installed before running ./configure and rebuild from that step. Run source rebuilds manually rather than from cron so dependency changes, network failures, or compiler errors are visible before they affect a working installation.
Install pip for Python 3.8 on Ubuntu
Understand Python 3.8 pip Packaging on Ubuntu
The system python3-pip package only wires pip to Ubuntu’s default interpreter (Python 3.14 on 26.04, 3.12 on 24.04, and 3.10 on 22.04), not to Python 3.8. For broader pip usage and Ubuntu defaults, refer to the dedicated guide on how to install pip on Ubuntu.
Ubuntu repository Python modules are built for the default interpreter, so compiled extension packages installed from apt (for example python3-psycopg2) will not load under Python 3.8 from Deadsnakes. Use python3.8 -m pip inside a virtual environment for third-party dependencies instead.
If you installed Python 3.8 from the PPA, install python3.8-venv to enable ensurepip and virtual environments:
sudo apt install python3.8-venv
If you compiled Python 3.8 from source, ensurepip is bundled by default, so you can skip this step unless you disabled it at build time.
To install pip specifically for Python 3.8, use either ensurepip or PyPA’s Python 3.8 bootstrap script:
Method 1: Install pip for Python 3.8 with ensurepip
Python includes a bundled bootstrap module named ensurepip that installs the version of pip packaged with the interpreter. This method is the simplest and works offline. Run the following to install or refresh pip for Python 3.8:
python3.8 -m ensurepip --upgrade
Expected output (exact versions vary, and PPA installs often default to a user-site install when run as a regular user):
Defaulting to user installation because normal site-packages is not writeable Looking in links: /tmp/tmp... Processing /tmp/tmp.../pip-23.0.1-py3-none-any.whl Installing collected packages: pip Successfully installed pip-23.0.1
This method avoids fetching an external script and works in minimal, offline, or restricted environments. Python 3.8.20 bundles pip 23.0.1, which is older than the newest Python 3.8-compatible pip release, so upgrade afterward if you need newer packaging fixes.
If the output warns that pip3.8 was installed in ~/.local/bin, either call pip as python3.8 -m pip (recommended) or add ~/.local/bin to your shell PATH.
python3.8 -m pip install --upgrade pip
Method 2: Install pip for Python 3.8 with get-pip.py
Alternatively, manually install pip using the official bootstrap script provided by the Python Packaging Authority (PyPA). The script requires python3.8-distutils on PPA installs and curl to download it:
sudo apt install python3.8-distutils curl
Now download the Python 3.8-specific script:
curl -fsSLO https://bootstrap.pypa.io/pip/3.8/get-pip.py
This uses the same curl flags described in the source download step. The /pip/3.8/ path ensures you get the version maintained for Python 3.8 specifically.
Run get-pip.py to Install pip for Python 3.8
After downloading the bootstrap script, execute it with Python 3.8 to install pip specifically for this interpreter:
python3.8 get-pip.py
Expected output (current versions change, and PyPA may cap pip to the newest release that still supports Python 3.8):
Defaulting to user installation because normal site-packages is not writeable Collecting pip<25.1 Downloading pip-25.0.1-py3-none-any.whl (1.8 MB) Collecting setuptools Downloading setuptools-...-py3-none-any.whl (...) Collecting wheel Downloading wheel-...-py3-none-any.whl (...) Installing collected packages: wheel, setuptools, pip Successfully installed pip-25.0.1 setuptools-... wheel-...
Ubuntu 24.04 and 26.04 mark the system
python3interpreter as externally managed (PEP 668), sopython3 -m pip installfor the system interpreter fails unless you use a virtual environment. This does not apply to Python 3.8 from the Deadsnakes PPA or source builds, but you should still usepython3.8 -m venvto isolate project dependencies.
Upgrade pip for Python 3.8
After installing pip, upgrade it to the latest version to access recent bug fixes and features. Always specify the python3.8 interpreter explicitly to avoid accidentally changing Ubuntu’s system pip environment:
python3.8 -m pip install --upgrade pip
You should see output similar to the following. The command may report that pip is already at the newest Python 3.8-compatible version:
Defaulting to user installation because normal site-packages is not writeable Requirement already satisfied: pip in /home/user/.local/lib/python3.8/site-packages (25.0.1)
Verify the Python 3.8 pip Version
Confirm pip installed correctly and check which version is bound to your Python 3.8 interpreter:
python3.8 -m pip --version
Expected output (version number and path vary by installation method):
pip 25.0.1 from /home/user/.local/lib/python3.8/site-packages/pip (python 3.8)
The path shown reflects both your Python 3.8 installation method and how you installed pip. PPA and source builds can place pip in a user site such as ~/.local/lib/python3.8/ when you run ensurepip or get-pip.py as a normal user, while virtual environments keep pip under the venv directory.
Manage Multiple Python Versions Safely on Ubuntu
If you need multiple versions of Python installed on your system and want to control which interpreter launches when you run python, follow these guardrails to avoid breaking core Ubuntu tools.
Do Not Replace Ubuntu’s Default Python 3 Interpreter
Ubuntu binds thousands of packages (APT, software-properties-gtk, update-manager, cloud-init, Ansible controllers, etc.) to the specific /usr/bin/python3 version that shipped with your release. Replacing that binary or symlink with Python 3.8 causes modules compiled for the distro version to disappear, and everyday commands immediately fail.
Leave
/usr/bin/python3untouched. Install additional interpreters via the Deadsnakes PPA,make altinstall, or tools like pyenv so they register as/usr/bin/python3.8or/opt/python3.8/bin/python3.8instead of replacing the system Python.
For example, symlinking /usr/bin/python3 to Python 3.8 immediately breaks apt update because the apt_pkg module is compiled specifically for Ubuntu’s stock interpreter.
Traceback (most recent call last):
File "/usr/bin/apt", line 27, in <module>
import apt_pkg
ModuleNotFoundError: No module named 'apt_pkg'
Use the same pattern when scripting: call python3.8 directly or install into isolated environments.
Use Python 3.8 Virtual Environments on Ubuntu
The safest approach for Python 3.8 workloads is creating per-project environments with python3.8 -m venv instead of modifying system-wide settings. This keeps Ubuntu’s stock Python untouched while giving every project the interpreter it requires, and avoids PEP 668 pip restrictions entirely. Refer to the guide on how to create a Python virtual environment on Ubuntu for detailed setup instructions.
For production deployments or teams managing multiple legacy applications, isolating Python 3.8 workloads by installing Docker on Ubuntu provides stronger isolation than virtual environments alone. Containers bundle the interpreter, dependencies, and application code into a reproducible unit that runs identically across development, staging, and production systems. This approach also simplifies security patching: rebuild the container image when vulnerabilities appear rather than updating each server individually.
Create a Python 3.8 Virtual Environment
To create an isolated environment for a legacy project, use the built-in venv module. This example creates an environment in a project directory and activates it:
mkdir -p ~/legacy-project && cd ~/legacy-project
python3.8 -m venv .venv
source .venv/bin/activate
Your shell prompt changes to show the active environment:
(.venv) user@hostname:~/legacy-project$
While the environment is active, python and pip automatically use Python 3.8 without the version suffix:
python --version
pip install requests
Expected output confirming the environment uses Python 3.8:
Python 3.8.20
Deactivate the environment when finished to return to your system shell:
deactivate
Store the .venv directory alongside your project code and add it to .gitignore. Include a requirements.txt file so collaborators can recreate the environment with pip install -r requirements.txt.
Troubleshooting Python 3.8 Installation Issues on Ubuntu
Fix Python 3.8 OpenSSL Module Build Failures
When compiling Python 3.8 on Ubuntu 22.04 or newer, the build may complete successfully but the ssl module fails to load with import errors. This happens because Ubuntu 22.04+ ships OpenSSL 3.x, while Python 3.8.0 through 3.8.15 were designed for OpenSSL 1.1.1.
Test if you have this issue:
python3.8 -c "import ssl; print(ssl.OPENSSL_VERSION)"
Expected output shows the OpenSSL version string (varies by release):
OpenSSL 3.x.x ...
If this command fails with ModuleNotFoundError: No module named '_ssl', you compiled an older Python 3.8 release against OpenSSL 3. The solution is to download Python 3.8.16 or newer (preferably 3.8.20) and recompile from the source-build configure step.
Fix Missing Python 3.8 Build Headers During Compilation
The configure script may report warnings about missing optional libraries when development headers are not installed. While Python will compile successfully, certain standard library modules like _ssl, _bz2, or _sqlite3 will be unavailable.
Check for disabled modules during configuration:
./configure --enable-shared 2>&1 | grep "disabled"
Example output when modules are missing:
checking for stdlib extension module _ssl... disabled checking for stdlib extension module _bz2... disabled
If the command prints nothing, no optional modules were disabled.
During make, you may instead see a summary of missing optional modules:
Python build finished successfully! The necessary bits to build these optional modules were not found: _dbm _tkinter _uuid nis
If you need those modules, install the matching development headers and rebuild. On Ubuntu, the common packages are libdb-dev for _dbm, uuid-dev for _uuid, tcl-dev and tk-dev for _tkinter, and libnsl-dev for nis.
sudo apt install libdb-dev uuid-dev tcl-dev tk-dev libnsl-dev
After installing the headers, re-run ./configure, make, and make altinstall to rebuild Python with those modules enabled.
If you see “Failed to build these modules” near the end of the compilation output, install the matching headers and rebuild from the configure step after the dependencies are present.
Fix Python 3.8 Shared Library Linking Errors
When running python3.8 after source compilation, you may see the exact error python3.8: error while loading shared libraries: libpython3.8.so.1.0: cannot open shared object file: No such file or directory. This happens when the dynamic linker cannot locate the Python shared library because it was installed outside standard library paths.
Verify the library exists:
find /usr/local -name "libpython3.8.so*"
Expected output showing the shared library location:
/usr/local/lib/libpython3.8.so.1.0 /usr/local/lib/libpython3.8.so
Then update the linker cache with the correct path:
sudo ldconfig /usr/local/lib
Verify the library is now findable:
ldconfig -p | grep python3.8
Expected output showing the library path:
libpython3.8.so.1.0 (libc6,x86-64) => /usr/local/lib/libpython3.8.so.1.0
Fix PEP 668 pip Errors for Python 3.8 on Ubuntu
On Ubuntu 24.04 and 26.04, the system python3 interpreter is externally managed (PEP 668). This affects python3 -m pip install for the system interpreter, not Python 3.8 from the PPA or source builds, but you should still use virtual environments to isolate Python 3.8 dependencies.
Example error output when you try to use the system interpreter with pip:
error: externally-managed-environment This environment is externally managed. To install Python packages system-wide, try: apt install python3-xyz If you want to use pip, create a virtual environment with python3 -m venv path/to/venv. note: You can override this with --break-system-packages (not recommended). hint: See PEP 668 for the detailed specification.
The recommended solution is creating a virtual environment for each project:
python3.8 -m venv myproject_env
source myproject_env/bin/activate
pip install package-name
Use Python 3.8 in GitHub Actions Ubuntu Runners
GitHub removed preinstalled Python 3.8 from Ubuntu runner images in 2025, but actions/setup-python can still download Python 3.8 archives when the exact version is not already in the runner cache. Add the setup step before running your legacy test job:
- uses: actions/setup-python@v6
with:
python-version: '3.8'
- run: python --version
If your workflow specifically needs Ubuntu-packaged Python 3.8 from the Deadsnakes PPA, use a PPA-based action or install the PPA inside the job. Keep that CI decision separate from host installation on a normal Ubuntu system.
Fix APT Breaking After Installing the Python 3.8 PPA on Ubuntu
If apt update or apt install fails with Python-related errors after adding the Deadsnakes PPA, ensure you did not accidentally replace Ubuntu’s system Python 3 interpreter. Check which interpreter /usr/bin/python3 points to:
readlink -f /usr/bin/python3
Expected output by release:
/usr/bin/python3.10 /usr/bin/python3.12 /usr/bin/python3.14
Confirm the binary is package-owned, then reinstall the package-managed default instead of switching Python with update-alternatives or a custom symlink:
dpkg -S /usr/bin/python3
sudo apt install --reinstall python3-minimal python3
Always invoke Python 3.8 explicitly using python3.8 rather than modifying the python3 symlink. If APT itself cannot run, use a recovery shell or live environment to restore the package-owned interpreter before continuing system maintenance.
Uninstall Python 3.8 from Ubuntu
Remove the Deadsnakes PPA Python 3.8 Installation
To remove Python 3.8 installed from the Deadsnakes PPA, first list the installed Python 3.8 packages so the removal command matches your system:
dpkg-query -W -f='${db:Status-Abbrev} ${binary:Package}\n' 'python3.8*' 'libpython3.8*' 2>/dev/null | grep '^ii' || echo "No Python 3.8 packages installed"
Example output when the common packages are installed:
ii python3.8 ii python3.8-venv ii python3.8-dev
Now remove the Python 3.8 packages you installed. Keep virtual environments and project directories backed up separately because package removal does not preserve broken project environments:
sudo apt remove python3.8 python3.8-dbg python3.8-venv python3.8-dev python3.8-distutils python3.8-lib2to3 python3.8-gdbm python3.8-tk
This removes the common Python 3.8 packages and optional components from the install sections. Change the package list to match what you actually installed.
Preview dependency cleanup separately before removing orphaned packages:
sudo apt autoremove --dry-run
Review the dry-run output carefully, because autoremovable packages can include libraries used by other local projects. If the preview only lists packages you no longer need, run the cleanup interactively:
sudo apt autoremove
Remove the Deadsnakes PPA only if you do not use it for other Python versions such as Python 3.11, 3.12, 3.13, or 3.14. If Python 3.8 was the only Deadsnakes package on this system, remove the source and optional pinning file:
sudo add-apt-repository --remove -y ppa:deadsnakes/ppa
sudo rm -f /etc/apt/preferences.d/python3.8.pref
sudo apt update
Ubuntu 22.04 typically creates a .list file for this PPA, while newer releases can create a .sources file. The add-apt-repository --remove command removes the correct source entry automatically. If you did not use pinning, the preferences file may not exist.
Verify no installed Python 3.8 packages remain:
dpkg-query -W -f='${db:Status-Abbrev} ${binary:Package}\n' 'python3.8*' 'libpython3.8*' 2>/dev/null | grep '^ii' || echo "No Python 3.8 packages installed"
Expected output after package removal:
No Python 3.8 packages installed
Remove the Source-Compiled Python 3.8 Installation
For source-compiled Python 3.8 installed via make altinstall, manually remove the binaries and libraries. If you used the default prefix (/usr/local), remove these files:
The following commands permanently delete the source-compiled installation. If you have custom configurations or scripts relying on this Python installation, back them up first with
cp -r /usr/local/lib/python3.8 ~/python38-backup.
sudo rm -rf /usr/local/bin/python3.8*
sudo rm -rf /usr/local/bin/pip3.8*
sudo rm -rf /usr/local/lib/python3.8
sudo rm -rf /usr/local/lib/libpython3.8*
sudo rm -rf /usr/local/include/python3.8
sudo ldconfig
If you used the update script or a dedicated build directory, remove it as well:
rm -rf ~/python3.8-build
Verify the source-compiled installation is removed:
hash -r
command -v python3.8 || echo "python3.8 not found"
Expected output when removal is complete:
python3.8 not found
When you compiled with a custom prefix like --prefix=/opt/python3.8, remove that directory:
sudo rm -rf /opt/python3.8
sudo ldconfig
Compare Default Python Versions and Python 3.8 Availability on Ubuntu
Use this quick reference when you need to confirm Ubuntu’s default Python version or decide whether Python 3.8 should come from the Deadsnakes PPA or a source build.
| Ubuntu Release | Default Python | Python 3.8 Availability | Recommended Path |
|---|---|---|---|
| Ubuntu 26.04 LTS | Python 3.14.x | Available from Deadsnakes PPA | Use Deadsnakes PPA unless you need a custom build |
| Ubuntu 24.04 LTS | Python 3.12.x | Available from Deadsnakes PPA | Use Deadsnakes PPA unless you need a custom build |
| Ubuntu 22.04 LTS | Python 3.10.x | Available from Deadsnakes PPA | Use Deadsnakes PPA unless you need a custom build |
If your legacy application can move off Python 3.8, use the newer version guides to install Python 3.10 on Ubuntu, install Python 3.11 on Ubuntu, install Python 3.12 on Ubuntu, install Python 3.13 on Ubuntu, or install Python 3.14 on Ubuntu to stay on supported interpreter branches.
Ubuntu 20.04 shipped Python 3.8 as its default interpreter, but it is outside the current Ubuntu LTS scope for this guide. Upgrade the base system first when you need normal security maintenance, then install Python 3.8 as a legacy side-by-side interpreter only for workloads that still require it.
Conclusion
Python 3.8.20 is ready to use on Ubuntu through the Deadsnakes PPA, with source builds still available for custom or offline environments. Keep your projects isolated with python3.8 -m venv and leave Ubuntu’s system python3 alone. When you are ready to move off Python 3.8, create a Python virtual environment on Ubuntu to manage the transition, or jump straight to a current interpreter with the guides to install Python 3.12 on Ubuntu or install Python 3.13 on Ubuntu.


Formatting tips for your comment
You can use basic HTML to format your comment. Useful tags currently allowed in published comments:
<code>command</code>command<strong>bold</strong><em>italic</em><blockquote>quote</blockquote>