Reputation: 29285
Is it possible to upgrade all Python packages at one time with pip
?
Note: that there is a feature request for this on the official issue tracker.
Upvotes: 2852
Views: 2016523
Reputation: 739
I use this one-liner setup as an alias to upgrade my pip3 packages:
pip3 list --outdated | sed '1,2d; s/ .*//' | xargs -n1 pip3 install -U
Or alternatively:
pip3 list --outdated | tail -n +3 | cut -d ' ' -f1 | xargs -n1 pip3 install -U
(note that while it's most likely the case these will work with most shells, your shell will have to support either sed and xargs for the first script or tail, cut, and xargs for the second script. These packages come preinstalled on most Unix or Unix-like systems)
pip3 list --outdated
gets a list of installed outdated pip3 packages:
pip3 list --outdated
Output:
Package Version Latest Type
-------------- ------- ------ -----
dbus-python 1.2.18 1.3.2 sdist
pycairo 1.20.1 1.25.1 sdist
PyGObject 3.42.1 3.46.0 sdist
systemd-python 234 235 sdist
sed '1,2d; s/ .*//'
or tail -n +3 | cut -d ' ' -f1
removes the first 2 lines of output and all characters inclusively after the first space character for each remaining line:
pip3 list --outdated | sed '1,2d; s/ .*//'
# or $pip3 list --outdated | tail -n +3 | cut -d ' ' -f1
Output:
dbus-python
pycairo
PyGObject
systemd-python
xargs -n1 pip3 install -U
passes the name of each package as an argument to pip3 install -U
(pip command to recursively upgrade all packages).
I ran some benchmarks and sed
appeared to be faster on my system. I used sed
and then tail
and cut
to read a text file input 5000 times and output it to /dev/null
and timed it. Here are the results I got on my machine:
sed:
------------------
real 0m9.188s
user 0m6.217s
sys 0m3.232s
tail-cut:
------------------
real 0m12.869s
user 0m13.913s
sys 0m9.921s
The benchmark setup can be found in the gist -> HERE <-
Upvotes: 5
Reputation: 177
In Windows, open Git Bash and execute
python -m pip list --outdated | awk 'BEGIN{xxx=1}{ if (xxx > 2) {print $1}; xxx+=1}' | xargs -n1 python -m pip install -U
Mission accomplished.
Upvotes: 0
Reputation: 834
I use the following to upgrade packages installed in /opt/...
virtual environments:
( pip=/opt/SOMEPACKAGE/bin/pip; "$pip" install -U $("$pip" list -o | sed -n -e '1,2d; s/[[:space:]].*//p') )
(unrelated tip, if you need shell variables, run commands inside a ( ... )
subshell so as to not pollute)
Upvotes: 0
Reputation: 547
That works for me for Python 3.12 out of the box, directly or in a virtual environment:
pip3 list -o | cut -f1 -d' ' | tr " " "\n" | awk '{if(NR>=3)print}' | cut -d' ' -f1 | xargs -n1 pip3 install -U
Upvotes: 0
Reputation: 1492
If you are using venv
, where you don't need to use sudo
:
pip list --outdated --format=json \
| jq -r '.[].name' \
| xargs -n1 pip install -U
Explanation
pip list --outdated --format=json
Returns a JSON-formatted list of all outdated packages.
jq -r '.[].name'
Extracts name
from the JSON output.
xargs -n1 pip install -U
Upgrades all Python packages one by one.
Upvotes: 3
Reputation: 673
If you are on macOS,
make sure you have Homebrew installed
install jq in order to read the JSON you’re about to generate
brew install jq
update each item on the list of outdated packages generated by pip3 list --outdated
pip3 install --upgrade `pip3 list --outdated --format json | jq '.[] | .name' | awk -F'"' '{print $2}'`
Upvotes: 2
Reputation: 1802
This option seems to me more straightforward and readable:
pip install -U `pip list --outdated | awk 'NR>2 {print $1}'`
(Update October 2024) Alternatively, to account for the eventuality of some package upgrades that fail (as suggested in the comments section by user3064538, rubo77, and mattmc3), I add here mattmc3's proposed solution:
pip list --outdated | awk 'NR>2 {print $1}' | xargs -n1 pip install -U
The explanation is that pip list --outdated
outputs a list of all the outdated packages in this format:
Package Version Latest Type
--------- ------- ------ -----
fonttools 3.31.0 3.32.0 wheel
urllib3 1.24 1.24.1 wheel
requests 2.20.0 2.20.1 wheel
In the AWK command, NR>2
skips the first two records (lines) and {print $1}
selects the first word of each line (as suggested by SergioAraujo, I removed tail -n +3
since awk
can indeed handle skipping records).
Upvotes: 112
Reputation: 45080
There isn't a built-in flag yet. Starting with pip version 22.3, the --outdated
and --format=freeze
have become mutually exclusive. Use Python, to parse the JSON output:
pip --disable-pip-version-check list --outdated --format=json | python -c "import json, sys; print('\n'.join([x['name'] for x in json.load(sys.stdin)]))" | xargs -n1 pip install -U
If you are using pip<22.3
you can use:
pip list --outdated --format=freeze | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 pip install -U
For older versions of pip
:
pip freeze --local | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 pip install -U
The grep
is to skip editable ("-e") package definitions, as suggested by @jawache. (Yes, you could replace grep
+cut
with sed
or awk
or perl
or...).
The -n1
flag for xargs
prevents stopping everything if updating one package fails (thanks @andsens).
Note: there are infinite potential variations for this. I'm trying to keep this answer short and simple, but please do suggest variations in the comments!
Upvotes: 2923
Reputation: 42465
Windows version after consulting the excellent documentation for FOR
by Rob van der Woude:
for /F "delims===" %i in ('pip freeze') do pip install --upgrade %i
You need to use cmd.exe
(i.e, Command Prompt); Windows nowadays defaults to PowerShell (especially if you use Windows Terminal) for which this command doesn't work directly. Or type cmd
at PowerShell to access Command Prompt.
Upvotes: 165
Reputation: 61
Another alternative to updating pip packages is:
pip install --upgrade $(pip freeze | cut -d '=' -f 1)
or
python -m pip install --upgrade $(pip freeze | cut -d '=' -f 1)
You can also use:
// python2
pip2 install --upgrade $(pip freeze | cut -d '=' -f 1)
python2 -m pip install --upgrade $(pip freeze | cut -d '=' -f 1)
// python3
pip3 install --upgrade $(pip freeze | cut -d '=' -f 1)
python3 -m pip install --upgrade $(pip freeze | cut -d '=' -f 1)
These commands will update all pip packages.
Upvotes: -1
Reputation: 1874
Sent through a pull-request to the pip folks; in the meantime use this pip library solution I wrote:
from operator import attrgetter
## Old solution:
# from pip import get_installed_distributions
# from pip.commands import install
## New solution:
from pkg_resources import working_set
from pip._internal.commands import install
install_cmd = install.InstallCommand()
options, args = install_cmd.parse_args(
## Old solution:
# list(map(attrgetter("project_name")
# get_installed_distributions()))
## New solution:
list(map(attrgetter("project_name"), working_set))
)
options.upgrade = True
install_cmd.run(options, args) # Chuck this in a try/except and print as wanted
Upvotes: 10
Reputation: 4849
As another answer here stated:
pip freeze --local | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 pip install -U
Is a possible solution: Some comments here, myself included, had issues with permissions while using this command. A little change to the following solved those for me.
pip freeze --local | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 sudo -H pip install -U
Note the added sudo -H
which allowed the command to run with root permissions.
To upgrade only outdated versions on a local / user environment for pip3
pip3 install --user -U `pip3 list -ol --format=json|grep -Po 'name": "\K.*?(?=")'`
The switch -ol
works similar to --outdated --local
or -o --user
. On Debian Testing you might also add the switch --break-system-packages
to install command. But do that only on your own risk. This command might be useful on super up-to-date systems where AI runs and anything with root is avoided. It helps porting from Stable Diffusion 1.5 to 2.1 with rocm support for example.
Upvotes: 3
Reputation: 9636
The following one-liner might prove of help:
(pip >= 22.3)
as per this readable answer:
pip install -U `pip list --outdated | awk 'NR>2 {print $1}'`
or as per the accepted answer:
pip --disable-pip-version-check list --outdated --format=json |
python -c "import json, sys; print('\n'.join([x['name'] for x in json.load(sys.stdin)]))" |
xargs -n1 pip install -U
(pip 20.0 < 22.3)
pip list --format freeze --outdated | sed 's/=.*//g' | xargs -n1 pip install -U
Older Versions:
pip list --format freeze --outdated | sed 's/(.*//g' | xargs -n1 pip install -U
xargs -n1
keeps going if an error occurs.
If you need more "fine grained" control over what is omitted and what raises an error you should not add the -n1
flag and explicitly define the errors to ignore, by "piping" the following line for each separate error:
| sed 's/^<First characters of the error>.*//'
Here is a working example:
pip list --format freeze --outdated | sed 's/=.*//g' | sed 's/^<First characters of the first error>.*//' | sed 's/^<First characters of the second error>.*//' | xargs pip install -U
Upvotes: 86
Reputation: 905
You can just print the packages that are outdated:
pip freeze | cut -d = -f 1 | xargs -n 1 pip search | grep -B2 'LATEST:'
Upvotes: 78
Reputation: 1200
This seems more concise.
pip list --outdated | cut -d ' ' -f1 | xargs -n1 pip install -U
Explanation:
pip list --outdated
gets lines like these
urllib3 (1.7.1) - Latest: 1.15.1 [wheel]
wheel (0.24.0) - Latest: 0.29.0 [wheel]
In cut -d ' ' -f1
, -d ' '
sets "space" as the delimiter, -f1
means to get the first column.
So the above lines becomes:
urllib3
wheel
Then pass them to xargs
to run the command, pip install -U
, with each line as appending arguments.
-n1
limits the number of arguments passed to each command pip install -U
to be 1.
Upvotes: 48
Reputation: 358
From yolk:
pip install -U `yolk -U | awk '{print $1}' | uniq`
However, you need to get yolk first:
sudo pip install -U yolk
Upvotes: 29
Reputation: 1248
pip freeze | %{$_.split('==')[0]} | %{pip install --upgrade $_}
Upvotes: 27
Reputation: 419
Use AWK update packages:
pip install -U $(pip freeze | awk -F'[=]' '{print $1}')
Windows PowerShell update
foreach($p in $(pip freeze)){ pip install -U $p.Split("=")[0]}
Upvotes: 21
Reputation: 2453
If you have pip<22.3
installed, a pure Bash/Z shell one-liner for achieving that:
for p in $(pip list -o --format freeze); do pip install -U ${p%%=*}; done
Or, in a nicely-formatted way:
for p in $(pip list -o --format freeze)
do
pip install -U ${p%%=*}
done
After this you will have pip>=22.3
in which -o
and --format freeze
are mutually exclusive, and you can no longer use this one-liner.
Upvotes: 14
Reputation: 150
You can try this:
for i in `pip list | awk -F ' ' '{print $1}'`; do pip install --upgrade $i; done
Upvotes: 15
Reputation: 151
There is not necessary to be so troublesome or install some package.
Update pip packages on Linux shell:
pip list --outdated --format=freeze | awk -F"==" '{print $1}' | xargs -i pip install -U {}
Update pip packages on Windows powershell:
pip list --outdated --format=freeze | ForEach { pip install -U $_.split("==")[0] }
Some points:
pip
as your python version to pip3
or pip2
.pip list --outdated
to check outdated pip packages.--format
on my pip version 22.0.3 only has 3 types: columns (default), freeze, or json. freeze
is better option in command pipes.Upvotes: 12
Reputation: 353
This ought to be more effective:
pip3 list -o | grep -v -i warning | cut -f1 -d' ' | tr " " "\n" | awk '{if(NR>=3)print}' | cut -d' ' -f1 | xargs -n1 pip3 install -U
pip list -o
lists outdated packages;grep -v -i warning
inverted match on warning
to avoid errors when updatingcut -f1 -d1' '
returns the first word - the name of the outdated package;tr "\n|\r" " "
converts the multiline result from cut
into a single-line, space-separated list;awk '{if(NR>=3)print}'
skips header linescut -d' ' -f1
fetches the first columnxargs -n1 pip install -U
takes 1 argument from the pipe left of it, and passes it to the command to upgrade the list of packages.Upvotes: 10
Reputation: 246
This seemed to work for me...
pip install -U $(pip list --outdated | awk '{printf $1" "}')
I used printf
with a space afterwards to properly separate the package names.
Upvotes: 9
Reputation: 1074
A JSON + jq answer:
pip list -o --format json | jq '.[] | .name' | xargs pip install -U
Upvotes: 8
Reputation: 890
Here's the code for updating all Python 3 packages (in the activated virtualenv
) via pip:
import pkg_resources
from subprocess import call
for dist in pkg_resources.working_set:
call("python3 -m pip install --upgrade " + dist.project_name, shell=True)
Upvotes: 6
Reputation: 2762
The below Windows cmd
snippet does the following:
- Upgrades
pip
to latest version.
requirements.txt
for any version specifiers.@echo off
Setlocal EnableDelayedExpansion
rem https://stackoverflow.com/questions/2720014/
echo Upgrading pip...
python -m pip install --upgrade pip
echo.
echo Upgrading packages...
set upgrade_count=0
pip list --outdated > pip-upgrade-outdated.txt
for /F "skip=2 tokens=1,3 delims= " %%i in (pip-upgrade-outdated.txt) do (
echo ^>%%i
set package=%%i
set latest=%%j
set requirements=!package!
rem for each outdated package check for any version requirements:
set dotest=1
for /F %%r in (.\python\requirements.txt) do (
if !dotest!==1 (
call :substr "%%r" !package! _substr
rem check if a given line refers to a package we are about to upgrade:
if "%%r" NEQ !_substr! (
rem check if the line contains more than just a package name:
if "%%r" NEQ "!package!" (
rem set requirements to the contents of the line:
echo requirements: %%r, latest: !latest!
set requirements=%%r
)
rem stop testing after the first instance found,
rem prevents from mistakenly matching "py" with "pylint", "numpy" etc.
rem requirements.txt must be structured with shorter names going first
set dotest=0
)
)
)
rem pip install !requirements!
pip install --upgrade !requirements!
set /a "upgrade_count+=1"
echo.
)
if !upgrade_count!==0 (
echo All packages are up to date.
) else (
type pip-upgrade-outdated.txt
)
if "%1" neq "-silent" (
echo.
set /p temp="> Press Enter to exit..."
)
exit /b
:substr
rem string substition done in a separate subroutine -
rem allows expand both variables in the substring syntax.
rem replaces str_search with an empty string.
rem returns the result in the 3rd parameter, passed by reference from the caller.
set str_source=%1
set str_search=%2
set str_result=!str_source:%str_search%=!
set "%~3=!str_result!"
rem echo !str_source!, !str_search!, !str_result!
exit /b
Upvotes: 5
Reputation: 2076
pip install --upgrade `pip list --format=freeze | cut -d '=' -f 1`
pip list --format=freeze
includes pip
and setuptools
. pip freeze
does not.
Upvotes: 1
Reputation: 799
If you want upgrade only packaged installed by pip, and to avoid upgrading packages that are installed by other tools (like apt, yum etc.), then you can use this script that I use on my Ubuntu (maybe works also on other distros) - based on this post:
printf "To update with pip: pip install -U"
pip list --outdated 2>/dev/null | gawk '{print $1;}' | while read; do pip show "${REPLY}" 2>/dev/null | grep 'Location: /usr/local/lib/python2.7/dist-packages' >/dev/null; if (( $? == 0 )); then printf " ${REPLY}"; fi; done; echo
Upvotes: 0
Reputation: 1467
pip freeze --local | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 pip install -U
Upvotes: -1
Reputation: 414715
To upgrade all local packages, you can install pip-review
:
$ pip install pip-review
After that, you can either upgrade the packages interactively:
$ pip-review --local --interactive
Or automatically:
$ pip-review --local --auto
pip-review
is a fork of pip-tools
. See pip-tools
issue mentioned by @knedlsepp. pip-review
package works but pip-tools
package no longer works. pip-review
is looking for a new maintainer.
pip-review
works on Windows since version 0.5.
Upvotes: 943