How To Install Python On Linux Ubuntu

How To Install Python On Linux Ubuntu

Reading time1 min
#Python#Linux#Development#Ubuntu#Python3#Pyenv

Mastering Python Installation on Ubuntu: Practical Guidance for Modern Development

Running Python on Ubuntu is rarely as simple as apt install python3. Production-grade development requires a setup that avoids legacy version pitfalls, obsolete system dependencies, and hidden incompatibilities buried within the OS image. Minor missteps propagate downstream: wrong interpreter, global package mess, or mismatched C headers will quietly sabotage builds and tooling.

System Python: Not Your Environment

Out of the box, Ubuntu LTS (e.g., 20.04) includes Python 3.8.x in /usr/bin/python3. Don't touch it unless you're prepared to break Ansible, cloud-init, or system utilities. Recall:

python3 --version
# Python 3.8.10

Notably, the community and upstream Python development move at a faster cadence—Python 3.11+ introduces core performance and typing features. Canonical’s repositories lag intentionally to preserve stability.

Note

Altering or upgrading system Python through apt upgrade or symbolic links is a direct path to system failure. Always treat /usr/bin/python3 as untouchable.

Installing Newer Python: Deadsnakes PPA

When current features are non-negotiable (e.g., tomllib, structural pattern matching), Deadsnakes PPA is the de facto source for modern Python releases on Ubuntu.

sudo apt update
sudo apt install -y software-properties-common
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt update

Confirm with:

apt-cache show python3.11 | grep Version

Install Python 3.11 and related build tools:

sudo apt install -y python3.11 python3.11-venv python3.11-dev
  • python3.11 – Interpreter
  • python3.11-venv – Virtual environments: essential for isolated dependencies
  • python3.11-dev – Headers for C extension builds

Switching Default Interpreter (Without Breaking the System)

By default, python3 points to the OS-maintained version. To steer workflows to 3.11 without interfering with system scripts, use update-alternatives:

sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 1
sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.11 2
sudo update-alternatives --config python3

Example output:

There are 2 choices for the alternative python3 (providing /usr/bin/python3).

  Selection    Path                Priority   Status
------------------------------------------------------------
* 1            /usr/bin/python3.8   1         auto mode
  2            /usr/bin/python3.11  2         manual mode

Select 2. Validate:

python3 --version
# Python 3.11.X

Gotcha: Some system scripts explicitly require 3.8's ABI. The change above only affects your shell and user-run scripts, not /usr/bin/env python3 within the systemd and snap stack.

pip, setuptools, and Basic Toolchain: Upgrade Immediately

Stock pip versions often trail security patches.

python3.11 -m ensurepip --upgrade
python3.11 -m pip install --upgrade pip setuptools wheel

Corollary: always use pip inside a virtual environment for non-global installations. This prevents contaminating interpreter-level site-packages.

Virtual Environments: Irreplaceable

Cluttered environments breed irreproducibility. Every modern Python project should be sandboxed.

mkdir ~/workspace/example
cd ~/workspace/example
python3.11 -m venv .venv
source .venv/bin/activate

Note your prompt now includes (.venv). Example package installation:

pip install fastapi uvicorn

Export current dependencies for reproducibility:

pip freeze > requirements.txt

Managing Multiple Python Versions: pyenv

For teams juggling heterogeneous projects (e.g., Django on 3.8 vs. CI test harnesses on 3.12), pyenv is a more scalable solution than update-alternatives. Its approach: user-level shims that override interpreter resolution in your shell—not system-wide.

First, prerequisites:

sudo apt update
sudo apt install -y --no-install-recommends \
  make 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 python-openssl git

Install pyenv:

curl https://pyenv.run | bash

Update shell RC (.bashrc or .zshrc):

export PATH="$HOME/.pyenv/bin:$PATH"
eval "$(pyenv init --path)"
eval "$(pyenv virtualenv-init -)"

Reload shell, then install alternative Python versions:

pyenv install 3.11.7
pyenv global 3.11.7
pyenv local 3.10.13  # Per project basis

Known issue: On Ubuntu in WSL2, ensure build dependencies for tk/tcl are present or python-tk imports will fail with cryptic ModuleNotFoundError: No module named '_tkinter'.

Diagnostics

  • PATH issues: which python3 or which python won’t always align with expected interpreter. $PATH order determines which is invoked.
  • C header errors: Native package installs (e.g., pip install lxml) may fail with fatal error: Python.h: No such file or directory. Reason: missing or mismatched pythonX.Y-dev.
  • Never run sudo pip install ...—this will cause silent, often permanent, interpreter breakage. Use venv or system packages.

Practical Example: Building a Flask Microservice

Assume requirement for flask==2.2.5 and Python 3.11+:

python3.11 -m venv venv
source venv/bin/activate
python -m pip install --upgrade pip
pip install flask==2.2.5 gunicorn
cat > app.py <<EOF
from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello, Ubuntu Python!"
EOF

gunicorn -w 2 -b 127.0.0.1:8000 app:app

When deploying to systemd or Docker, always pin your interpreter and dependencies explicitly, rather than assuming the system version.

Summary

Proper Python installation on Ubuntu is not a one-line operation—it’s an exercise in avoiding systemic conflicts and ensuring maintainability. Stick to these key principles:

  • Never “upgrade” system Python, always install side-by-side.
  • Prefer virtual environments for every project.
  • Leverage pyenv or update-alternatives for multi-version management.
  • Validate with --version and explicit interpreter calls (python3.11 ...).

Beyond the basics, this approach sidesteps subtle OS/application integration failures, especially across CI/CD pipelines and collaborative projects. For enterprise, containerize with official Docker Python images to further decouple from host OS concerns.

Alternate Approaches

No install guide is perfect; trade-offs exist based on workflow, security policies, and project requirements. But with this foundation, expect fewer surprises.


For comprehensive Linux-Python workflow tips, check the related posts.