How to upgrade all Python packages with pip
pip is the package installer for Python. It has no upgrade-all command, so
everybody copies a shell one-liner from somewhere. This article shows the
better version, and demonstrates the failure the one-liners can leave behind.
There is no built-in command
pip install --upgrade takes package names, and there is no way to say “all of
them”. That omission is deliberate — upgrading everything at once is rarely
what a working project wants — but the need still comes up, especially in a
scratch environment.
Start by looking
$ pip list --outdated
Package Version Latest Type
certifi 2022.9.24 2026.7.22 wheel
charset-normalizer 2.1.1 3.5.1 wheel
idna 3.3 3.19 wheel
requests 2.28.1 2.34.2 wheel
urllib3 1.26.12 2.7.0 wheel
That is worth doing on its own before you change anything.
The one-liner everybody copies
$ pip freeze | cut -d= -f1 | xargs pip install -U
It works often enough to keep being shared, and it has two problems.
The first is pip freeze. Its job is to produce a reproducible requirements
file, so it emits more than plain names — editable installs as -e ..., VCS
checkouts as full git+https://... URLs, and local packages as file paths.
cut -d= -f1 turns each of those into something that is not a package name,
and pip install -U then either fails or installs the wrong thing.
Use the machine-readable output instead:
$ pip list --outdated --format=json
[{"name": "certifi", "version": "2022.9.24", "latest_version": "2026.7.22", ...
which gives you exactly the names, and only the ones that need upgrading:
$ pip list --outdated --format=json \
| python -c "import json,sys; print(' '.join(p['name'] for p in json.load(sys.stdin)))"
certifi charset-normalizer idna requests urllib3
Feed that to a single pip install --upgrade and you are done:
$ pip install --upgrade certifi charset-normalizer idna requests urllib3
Note the single command. That matters, and it is the second problem.
Upgrading one at a time can break the set
Most of the one-liners run pip install -U once per package. pip resolves
dependencies per install command, so a loop of n commands is not the same
as one command with n packages.
Here is that going wrong. Start from a consistent environment where requests 2.28.1 requires urllib3 < 1.27:
installing requests 2.28.1 again, which needs urllib3 < 2:
No broken requirements found.
Now upgrade only urllib3, exactly as a per-package loop would:
requests 2.28.1 requires urllib3<1.27,>=1.21.1, but you have urllib3 2.7.0 which is incompatible.
pip warns during the install, and the environment is now broken. If that warning scrolled past in a hundred lines of output, nothing else tells you — until something raises at runtime.
The command that finds it afterwards is one people rarely know:
$ pip check
requests 2.28.1 has requirement urllib3<1.27,>=1.21.1, but you have urllib3 2.7.0.
Run pip check after any bulk upgrade. It is instant and it either says
No broken requirements found or names the problem precisely.
What I would actually do
For a real project, do not upgrade everything. Pin your dependencies, upgrade
deliberately, and let a tool that resolves the whole set at once do the work —
pip-tools, Poetry or uv all do this,
and all of them produce a lock file so the result is reproducible.
Two smaller things that help regardless:
Work in a virtual environment. Upgrading everything in a system Python can
break tools that came from your distribution’s package manager.
venv is in the standard
library.
Look before you leap. pip install --dry-run --upgrade ... shows you what
would change without changing it, which is worth the extra ten seconds when the
list is long.
For a scratch environment
If it really is a throwaway environment and you just want everything current:
$ pip list --outdated --format=json \
| python -c "import json,sys; print(' '.join(p['name'] for p in json.load(sys.stdin)))" \
| xargs -r pip install --upgrade
$ pip check
One resolution, no freeze parsing, and a check at the end. The -r on
xargs stops it running pip install --upgrade with no arguments when nothing
is outdated.
About Netcup (advertisement)
The German host Netcup offers, among other things, affordable and powerful web hosting packages, KVM-based root servers and dedicated servers. With our voucher codes you can save even more (6€ off your first order, 30% off all KVM-based root servers, ...).