You’ve been installing Python packages the same way for years. pip install requests. It always worked.
Then you upgraded to Ubuntu 24.04 (or Debian 12, or Fedora 39+), ran the same command, and got this:
error: externally-managed-environment
× This environment is externally managed
╰─> To install Python packages system-wide, try apt install
python3-xyz, where xyz is the package you are trying to install.
Your first instinct is that something broke. But nothing is broken. This is a deliberate change called PEP 668, and it’s actually protecting you from breaking your operating system.
What PEP 668 Actually Means (In Plain English)
Here’s the problem PEP 668 solves:
Your Linux operating system uses Python internally. System tools, package managers, and configuration scripts are written in Python and depend on specific versions of Python packages.
When you run pip install requests, pip installs the latest version of requests and all its dependencies into the system Python’s global site-packages directory. This overwrites whatever version was already there.
If Ubuntu needed requests version 2.28 for an internal tool, and pip just installed version 2.32, that internal tool might break. Worse — pip might upgrade urllib3 or certifi to versions that are incompatible with Ubuntu’s own packages, breaking apt itself.
This has actually happened. People have bricked their Linux installations by running pip install carelessly. PEP 668 prevents this.
When your Linux distribution marks its Python as “externally managed,” it’s saying: “I manage the system Python. Don’t install packages here. Use a virtual environment instead.”
Fix 1: Use a Virtual Environment (Recommended)
This is the correct, intended solution. A virtual environment gives you a private Python installation where pip works exactly like it always has — no restrictions, no conflicts.
Install venv if needed (Ubuntu/Debian):
sudo apt install python3-venv
Create a virtual environment:
python3 -m venv myproject
Activate it:
source myproject/bin/activate
Your terminal prompt changes to (myproject). You’re now inside the virtual environment.
Install packages normally:
pip install requests pandas flask
These packages install into myproject/lib/ — completely separate from the system Python.
Run your code:
python script.py
Deactivate when done:
deactivate
That’s it. pip works. Your system is safe. Everyone is happy.
Pro tip: Create the venv inside your project folder so everything stays together:
mkdir ~/my-app
cd ~/my-app
python3 -m venv .venv
source .venv/bin/activate
pip install requests
Fix 2: Use pipx for Command-Line Tools
If you want to install a Python command-line tool (not a library for your code), use pipx. It creates an isolated environment for each tool automatically.
Install pipx:
sudo apt install pipx
pipx ensurepath
Close and reopen your terminal after ensurepath.
Install tools:
pipx install black # code formatter
pipx install ruff # fast linter
pipx install youtube-dl # video downloader
pipx install httpie # HTTP client
pipx install cookiecutter # project templates
Each tool gets its own isolated environment. They don’t conflict with each other or with your system Python.
When to use pipx vs venv:
- pipx → for standalone tools you run from the command line (like
black myfile.py) - venv → for libraries your project code imports (like
import requests)
Fix 3: Use apt to Install System Packages
Before reaching for pip, check if the package exists as a system package. Ubuntu and Debian include thousands of Python packages in their repositories.
Search for a package:
apt search python3-requests
apt search python3-flask
Install it:
sudo apt install python3-requests
Packages installed this way are managed by apt and are guaranteed to be compatible with your system Python.
When to use apt:
- You need the package available system-wide
- You’re writing a system script that runs outside of a virtual environment
- The package is a dependency for other system tools
The downside: apt packages are often older versions. If you need the latest version of a package, use a virtual environment with pip.
The “Quick Hack” That Can Break Your System
You’ll see this advice everywhere:
pip install requests --break-system-packages
Or the permanent version — creating ~/.config/pip/pip.conf:
[global]
break-system-packages = true
This works. It bypasses the PEP 668 protection and installs packages system-wide, just like the old days.
But it’s dangerous. Here’s why:
When pip installs requests, it also installs (or upgrades) dependencies like urllib3, certifi, charset-normalizer, and idna. These are the same packages that Ubuntu system tools depend on. If pip installs an incompatible version, you could break:
- apt — Ubuntu’s package manager is written in Python
- systemd services that use Python scripts
- GNOME tools and system utilities
- Unattended upgrades and security update mechanisms
The only time --break-system-packages is acceptable:
- Inside a Docker container (it’s disposable)
- Inside a CI/CD pipeline (it rebuilds every time)
- On a VM you don’t care about
Never on your daily-use Linux machine.
Quick Decision Tree
Here’s how to decide which method to use:
“I’m building a project and need libraries like requests, pandas, flask”
→ Use a virtual environment (python3 -m venv)
“I want to install a command-line tool like black, ruff, or youtube-dl”
→ Use pipx (pipx install tool_name)
“I need a package available system-wide for a system script”
→ Use apt (sudo apt install python3-package_name)
“I’m inside a Docker container”
→ Use pip install with --break-system-packages (the container is disposable)
“I just want pip to work like before”
→ Use a virtual environment. It takes 10 seconds to set up and pip works identically inside it.
Common Questions After the Switch
“Do I need a new virtual environment for every project?”
It’s recommended but not strictly required. Each virtual environment is isolated, so packages installed in one don’t affect another. This prevents dependency conflicts between projects. But if you have two small scripts that use the same packages, they can share a venv.
“My script worked before the upgrade and now it doesn’t”
Your script was probably using system-installed Python packages (via pip or apt). After upgrading, the PEP 668 restriction kicked in. Create a virtual environment, activate it, reinstall the packages with pip, and your script will work again.
“I see python3-full — should I install that?”
On Ubuntu/Debian, python3-full installs the complete Python standard library including venv, tkinter, distutils, and idle. It’s not always installed by default to save space. If you’re doing Python development, install it:
sudo apt install python3-full
This gives you everything you need to create virtual environments without extra steps.
If You Found This Guide Helpful
Check out our other troubleshooting resources:
- How to Fix “Permission Denied” on Linux — chmod, chown, and sudo explained
- apt vs Snap vs Flatpak — Troubleshooting Guide — when package managers conflict
- How to Fix “Could Not Get Lock /var/lib/dpkg/lock” on Ubuntu — fix stuck package manager
Frequently Asked Questions
Can I remove the externally-managed marker file?
Technically yes — you can delete /usr/lib/python3.X/EXTERNALLY-MANAGED. But this defeats the entire purpose of PEP 668 and puts your system at risk. If you delete this file and later run pip install, pip will happily overwrite system packages without warning. Don’t do this on a machine you depend on.
Does this affect Conda or Anaconda?
No. Conda manages its own Python installations and environments independently. If you use Conda, you won’t encounter the externally-managed-environment error because Conda doesn’t use the system Python.
I’m on WSL (Windows Subsystem for Linux). Does this apply?
Yes. WSL runs a real Linux distribution (usually Ubuntu), so PEP 668 applies. Create virtual environments inside WSL the same way you would on a native Linux machine.
Why doesn’t macOS have this restriction?
macOS with Homebrew does have it. If you installed Python via Homebrew on macOS, you’ll see the same “externally-managed-environment” error. The fix is the same — use virtual environments or pipx.
Last updated: February 2026 | Tested on Ubuntu 24.04 LTS, Ubuntu 24.10, Debian 12, Fedora 41 — Python 3.12, 3.13