Python on Debian

Debian Development Machine Setup

Chapter 5 ยท Python the Debian Way

Python is already on devserver, because Debian's own tools depend on it. That is exactly what makes it easy to get wrong. If you install packages into the Python that the operating system uses, you can break the operating system. Debian 12 and 13 refuse to let you do it by accident, and this chapter explains why, and gives you three clean ways of working: virtual environments for projects, pipx for command-line tools, and pyenv for when you need a different Python version. It builds directly on the “which copy runs?” habit from Chapter 3.

The Python You Already Have

Debian 13 ships Python 3.13 (the current package is 3.13.5). Check it with the tools from Chapter 3:

python3 --version type -a python3 dpkg -S "$(command -v python3)" apt policy python3

You should see one copy, /usr/bin/python3, owned by a Debian package. That is the system Python. Note there is no plain python command, only python3. (An optional package, python-is-python3, adds one, but you do not need it.)

A fresh desktop install often has the interpreter but not everything you need to develop. Install the extras now:

sudo apt install python3-pip python3-venv python3-dev pipx
PackageWhy
python3-pipThe pip installer.
python3-venvDebian splits virtual-environment support into its own package, so python3 -m venv needs this.
python3-devHeader files for compiling Python extensions written in C. Many packages need it when they install.
pipxInstalls Python command-line tools each in their own isolated environment. Debian 13 has version 1.7.1.

Why pip install Refuses

Now try the thing every tutorial tells you to do:

pip install requests

On Debian 12 and 13 this stops with an error that begins error: externally-managed-environment, and explains that the environment is managed by the operating system. This is not a fault. Debian is following PEP 668, a Python standard that lets a distribution mark its Python as “externally managed”, so pip will not modify it. Debian marks the interpreter with a file named EXTERNALLY-MANAGED in the standard-library directory, and pip checks for it.

What it is protecting you from
Debian's own tools are written in Python and depend on particular versions of particular libraries. If pip installed or upgraded one of those libraries system-wide, a Debian tool could stop working, and the fault would appear somewhere unrelated to what you did. Keeping your packages out of the system Python removes that whole category of problem.
The override exists. Don't use it as a habit.
pip install PACKAGE --break-system-packages overrides the safeguard, and the Debian wiki mentions it. It puts you back in exactly the situation the rule prevents. Reserve it for a throwaway machine, never for devserver. Also avoid sudo pip install, which is the same mistake with more authority.

Which Tool for Which Job

Instead of overriding the rule, choose the right tool. The question to ask is: what am I installing?

You want to…UseBecause
Write a project that needs librariesA virtual environmentEach project gets its own libraries and versions, separate from the system and from other projects.
Install a command-line tool written in PythonpipxThe tool gets its own private environment but is available as an ordinary command.
Get a Python version Debian does not shippyenvBuilds and switches between other Python versions in your home directory.
Get a library that an apt-installed program needsapt (python3-NAME)Debian packages many libraries as python3-* and keeps them consistent with the system.

Virtual Environments

A virtual environment (venv) is a folder containing its own copy of the Python interpreter link and its own place for packages. Create one inside each project, and activate it when you work there:

mkdir -p ~/projects/demo && cd ~/projects/demo python3 -m venv .venv source .venv/bin/activate # Your prompt now shows (.venv). Check which copies the shell finds: type -a python3 pip --version pip install requests pip list deactivate

After source .venv/bin/activate, type -a python3 lists the venv's copy first. That is the whole trick: activation puts the environment's bin directory at the front of your PATH, so python3 and pip now mean the ones inside the venv. pip install requests works, and the package lands inside .venv, not in the system. deactivate puts the PATH back.

Never commit the venv, and never move it
A venv is not portable, because scripts inside it contain absolute paths. If you move a project, recreate the environment rather than copying it. Since Python 3.13, python3 -m venv writes a .gitignore file into the environment so that Git ignores it automatically. What you should commit is a list of the packages the project needs, which is the next step.

Recording and recreating an environment

# With the venv active: write down exactly what is installed pip freeze > requirements.txt # Later, on any machine: build a fresh venv and install from the list python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt

Because a venv is disposable, you can delete .venv and rebuild it from requirements.txt in seconds. That is what makes it safe to experiment.

pipx: Tools, Not Libraries

Some Python software is not a library for your project but a program you want to run: a code formatter, an HTTP client, a linter. pipx installs each one into its own private virtual environment and puts its command where you can run it. The Debian wiki recommends pipx as the easiest way to work with the externally-managed rule.

# One-time: make sure ~/.local/bin is on your PATH (log out and in afterwards) pipx ensurepath # Install a tool, and see what pipx manages pipx install httpie pipx list http --version command -v http pipx upgrade httpie pipx uninstall httpie

The http command works from anywhere, yet its libraries are isolated and cannot clash with anything else. The command itself sits in ~/.local/bin, which Chapter 3 listed as a place where software installed for one user lives outside apt.

pyenv: Other Python Versions

Debian 13 gives you one Python, 3.13. That is fine most of the time. But a project may need an older version to match a server, or you may want to test on a newer one. pyenv builds extra Python versions from source into your home directory, and lets you choose per project.

Because it compiles Python, pyenv needs a set of build libraries first. The pyenv project's own suggested list for Debian is:

sudo apt update; sudo apt install make build-essential libssl-dev zlib1g-dev \ libbz2-dev libreadline-dev libsqlite3-dev curl git \ libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev libzstd-dev

pyenv's documentation offers a one-line installer that pipes a downloaded script into bash. It is worth knowing that running a downloaded script blindly is exactly what the verify-before-you-trust habit from Chapter 1 warns against, so this course uses the other documented method: clone the project and read what you are running.

git clone https://github.com/pyenv/pyenv.git ~/.pyenv

Then add these lines to ~/.bashrc (and the same lines to ~/.profile, as the pyenv documentation advises):

export PYENV_ROOT="$HOME/.pyenv" [[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH" eval "$(pyenv init - bash)"

Open a new terminal, then use it:

pyenv install --list | grep -E '^\s*3\.12' # see what is available pyenv install 3.12.x # replace with a real version from the list pyenv versions cd ~/projects/demo pyenv local 3.12.x # writes a .python-version file in this folder python --version

pyenv local writes a .python-version file, so a project always uses the version you chose for it, and the file can be committed to Git. Building takes a few minutes; that is normal.

Chapter 3's warning, in action
pyenv works by putting its own shims directory at the front of your PATH. That means type -a python3 now lists a pyenv shim before /usr/bin/python3, which is exactly the “two copies, first one wins” situation from Chapter 3, arranged on purpose. If you ever wonder which Python is running, type -a python3 and pyenv versions answer it.
You may not need pyenv at all
Do not install pyenv just because it exists. If 3.13 does everything you need, skip it: every extra tool on the PATH is one more thing to explain when something behaves oddly. Install it the day a real project needs a different version.

When apt Is the Right Answer

Debian packages many Python libraries as python3-NAME (for example python3-requests). Use apt when a library is needed by a program you installed with apt, or when you want a tool that is part of the operating system's own ecosystem. The catch is that the version is whatever Debian froze at release, often older than PyPI's latest, which is why projects use venvs. Check with the Chapter 3 tools before you choose:

apt policy python3-requests apt search --names-only '^python3-flask$'

For deeper Python work, see the Python Fundamentals course. Here we only need the machine to be set up so that course, and every project after it, starts cleanly.

Hands-On Exercises

Exercise 1

Install the four packages from this chapter and verify them with the Chapter 3 tools. Then run pip install requests outside any virtual environment, copy the error, and explain in your own words what PEP 668 is and why Debian enforces it. Finally, do the same install correctly inside a venv.

๐Ÿ“„ View solution
Exercise 2

Prove a virtual environment is disposable. In a new project folder, create a venv, install requests, freeze the requirements, delete the venv completely, recreate it from requirements.txt, and confirm the package is back. Also check what type -a python3 reports before, during and after activation.

๐Ÿ“„ View solution
Exercise 3

Use pipx to install a command-line tool, and show where its command lives and that its libraries are not visible to the system Python. Then, for each of five scenarios you invent or are given (a Flask project, a code formatter, a project that needs Python 3.11, a library used by an apt-installed program, a quick throwaway experiment), name the right tool and justify the choice.

๐Ÿ“„ View solution

Chapter 5 Quick Reference

  • Debian 13 ships Python 3.13 as python3 (no plain python); it is the system Python, used by Debian's own tools
  • Install: sudo apt install python3-pip python3-venv python3-dev pipx
  • pip install outside a venv fails with externally-managed-environment (PEP 668): a deliberate protection, not a fault
  • Avoid --break-system-packages and sudo pip install
  • Projects: python3 -m venv .venv, source .venv/bin/activate, deactivate
  • Record and rebuild: pip freeze > requirements.txt, pip install -r requirements.txt
  • Venvs are not portable and should not be committed; Python 3.13 adds a .gitignore inside automatically
  • Command-line tools: pipx install NAME, pipx list, pipx upgrade, pipx uninstall, plus pipx ensurepath once
  • Other Python versions: pyenv (clone to ~/.pyenv, needs the build libraries; pyenv local VERSION writes .python-version)
  • Activation and pyenv both work by putting their own directory first on PATH; type -a python3 shows which copy wins
  • Use apt (python3-NAME) for libraries needed by apt-installed programs