The Problem with System Python

On most Linux distributions, Python is a core system tool. Debian and Ubuntu ship with Python 3 pre-installed because system utilities depend on it. This creates a fundamental tension: you need a specific Python version for your project, but modifying the system Python can break OS-level scripts and tools.

The solution is to never touch system Python and instead manage your own Python installations independently. Here's how to do it cleanly.

Step 1: Install pyenv

pyenv lets you install and switch between multiple Python versions without touching the system installation. Install it via the official installer:

curl https://pyenv.run | bash

Then add the following to your ~/.bashrc or ~/.zshrc:

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

Reload your shell: source ~/.bashrc

Step 2: Install Build Dependencies

pyenv compiles Python from source, so you need build dependencies first. On Debian/Ubuntu:

sudo apt update && sudo apt install -y \
  build-essential libssl-dev zlib1g-dev \
  libbz2-dev libreadline-dev libsqlite3-dev \
  libncursesw5-dev xz-utils tk-dev libxml2-dev \
  libxmlsec1-dev libffi-dev liblzma-dev

Step 3: Install a Python Version

List available Python versions with pyenv install --list, then install your preferred version:

pyenv install 3.12.3
pyenv global 3.12.3

Verify with python --version. You can also set a per-project version using pyenv local 3.11.8 inside a project directory — this writes a .python-version file that pyenv picks up automatically.

Step 4: Use Virtual Environments for Every Project

Even with pyenv, you should always use a virtual environment per project to isolate dependencies. Python's built-in venv module is sufficient:

cd ~/projects/my-app
python -m venv .venv
source .venv/bin/activate

Once activated, your prompt changes and pip install affects only this environment. To deactivate: simply run deactivate.

Step 5: Manage Dependencies with pip and a requirements file

Install packages inside your virtual environment and freeze them to a file:

pip install requests flask
pip freeze > requirements.txt

Anyone cloning your project can recreate the environment with:

python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt

Optional: Use pipx for CLI Tools

For Python-based command-line tools (like black, httpie, or cookiecutter), use pipx rather than installing them into your global environment. pipx installs each tool in its own isolated environment but makes it available system-wide:

pip install pipx
pipx install black
pipx install httpie

Quick Reference

TaskCommand
Install Python versionpyenv install 3.12.3
Set global Pythonpyenv global 3.12.3
Create virtual envpython -m venv .venv
Activate virtual envsource .venv/bin/activate
Freeze dependenciespip freeze > requirements.txt
Install CLI toolpipx install tool-name

With this setup you get a clean, reproducible, and maintainable Python workflow that won't interfere with your system — now or in the future.