How To Download Python On Linux

How To Download Python On Linux

Reading time1 min
#Python#Linux#Programming#pyenv#LinuxPython#PythonInstallation

Python on Linux: Installation Methods for Real-World Projects

Modern Linux environments often ship with Python pre-installed. Yet for any workflow beyond basic scripting—especially when juggling multiple applications or CI/CD pipelines—the default system Python isn’t just limiting, it can be a liability.

Here’s how to control your runtime, sidestep upstream version lags, and avoid the classic “system tools broken by Python upgrade” pitfall. This is what experienced devs do when project requirements inevitably diverge from the distro’s defaults.


System Python: Asset or Hidden Trap?

System Python emerges from package repositories primarily to support distro utilities (yum, dnf, apt). Tinkering with it often leads to unstable or broken desktops—apt, for instance, depends on specific Python versions. Here’s an illustrative error I encountered on an Ubuntu 20.04 VM after an aggressive upgrade:

Traceback (most recent call last):
  File "/usr/bin/lsb_release", line 25, in <module>
    import lsb_release
ModuleNotFoundError: No module named 'lsb_release'

Key takeaway: Never overwrite or remove your distro’s default Python binary—leave /usr/bin/python3 alone. For actual software development, use one of these approaches:


Approach 1: Install via Package Manager

When to use: Tight deadlines, minimal setup overhead, or when distributing scripts in homogeneous environments.

Ubuntu/Debian

sudo apt update
sudo apt install python3.10 python3.10-venv python3-pip
python3.10 --version
  • Note: Actual available versions depend on your release. On Ubuntu 22.04, python3.10 is default. For older distros, use deadsnakes PPA or similar.

RHEL/Fedora

sudo dnf install python3.10 python3-pip
python3.10 --version
  • Fedora modules allow parallel install of different Python stacks (try sudo dnf module list python).

Warning: Installing a new minor version (e.g., 3.11 alongside 3.10) may introduce parallel interpreters but doesn’t guarantee isolated environments. Overlapping site-packages is common.

Tip

Immediately set up a local environment:

python3.10 -m venv ./venv
source ./venv/bin/activate

This prevents polluting system site-packages—essential with legacy apps or CI runners.


Approach 2: pyenv — Multi-Version Isolation

Serious development? Use pyenv. It builds and maintains arbitrary Python versions in user space (~/.pyenv). No root needed, no collisions with /usr/bin. Version switching is one command.

Installation (Partial, for Ubuntu 22.04/20.04):

sudo apt update && sudo apt install -y build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm \
libncurses5-dev xz-utils tk-dev libffi-dev liblzma-dev git

curl https://pyenv.run | bash
echo -e '\nexport PATH="$HOME/.pyenv/bin:$PATH"\neval "$(pyenv init --path)"\neval "$(pyenv virtualenv-init -)"' >> ~/.bashrc
exec $SHELL
  • Known issue: Missing build dependencies cause opaque failures deep in compilation logs.

Usage Example

Install and select Python 3.11.2 just for one project:

pyenv install 3.11.2
cd ~/work/project-x
pyenv local 3.11.2
python --version  # → Python 3.11.2
  • Side note: For compiled modules, differing OpenSSL or zlib versions may cause obscure import errors (ImportError: libssl.so.1.1: cannot open shared object file).

Why pyenv?

  • Project-specific interpreter selection via .python-version.
  • No interference with system Python.
  • Per-user virtual environments with pyenv virtualenv.

Approach 3: Compile From Source — For Ultimate Precision

When package maintainers lag months behind upstream, or when project build flags demand absolute control (--enable-optimizations, LTO support), build Python yourself.

Workhorse Script:

PY_VER=3.11.2
curl -O https://www.python.org/ftp/python/$PY_VER/Python-$PY_VER.tgz
tar xf Python-$PY_VER.tgz
cd Python-$PY_VER

# Install required libraries (Debian/Ubuntu shown)
sudo apt install -y build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev \
libncurses5-dev xz-utils tk-dev libffi-dev liblzma-dev uuid-dev

./configure --prefix=$HOME/.local/python-$PY_VER --enable-optimizations
make -j$(nproc)
make install

Add to PATH:

echo 'export PATH="$HOME/.local/python-3.11.2/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
python3.11 --version

Trade-off: You must update or rebuild manually for security patches. This method leaves no package manager record—good for stability, risky for compliance.

Practical Gotcha

If LD_LIBRARY_PATH isn’t set and you enabled non-standard build options, dynamic linking can break at runtime:

error while loading shared libraries: libpython3.11.so.1.0: cannot open shared object file

Summary Table

MethodUse-caseKey BenefitsKey Drawbacks
System Package ManagerQuick install, conservative opsEase, system integrationOutdated, fragile on upgrades
pyenvMulti-project dev, per-user needsFast switching, no rootExtra tooling, some quirks
Build from SourceCustom builds, bleeding edgeTotal control, reproducibleManual upgrades, less support

Routine Practices & Non-Obvious Tips

  • Always use virtual environments (venv, virtualenv) with any non-system Python.
  • Automate interpreter switching in your shell prompt—look into pyenv’s shell hooks.
  • For reproducible builds (e.g., Docker), stick to source compilation plus explicit config flags.

Note: On production servers, pin both the Python interpreter and packages—builds can differ subtly between machines.


No method is perfect—choose what survives your tooling, deployment, and upgrade requirements. In CI or containerized workflows, prefer pinned, source-built interpreters; for local dev, pyenv is nearly always the path of least headaches.

For advanced environment management or questions about distroless deployment, reach out or request a detailed follow-up.