thedjpetersen
thedjpetersen

Reputation: 29285

How to upgrade all Python packages with pip

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

Answers (30)

Snap
Snap

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)

  1. 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
    
  2. 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
    
  3. 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

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

usretc
usretc

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

SmileMZ
SmileMZ

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

arainchi
arainchi

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

  1. pip list --outdated --format=json

Returns a JSON-formatted list of all outdated packages.

  1. jq -r '.[].name'

Extracts name from the JSON output.

  1. xargs -n1 pip install -U

Upgrades all Python packages one by one.

Upvotes: 3

Dio Chou
Dio Chou

Reputation: 673

If you are on macOS,

  1. make sure you have Homebrew installed

  2. install jq in order to read the JSON you’re about to generate

    brew install jq
    
  3. 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

Marc
Marc

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

rbp
rbp

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

Piotr Dobrogost
Piotr Dobrogost

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

Frederick Valdez
Frederick Valdez

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

Samuel Marks
Samuel Marks

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

thebeancounter
thebeancounter

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

raratiru
raratiru

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

janrito
janrito

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

Shihao Xu
Shihao Xu

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

tkr
tkr

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

Apeirogon Prime
Apeirogon Prime

Reputation: 1248

Windows PowerShell solution

pip freeze | %{$_.split('==')[0]} | %{pip install --upgrade $_}

Upvotes: 27

JohnDHH
JohnDHH

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

German Lashevich
German Lashevich

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

3WA羽山秋人
3WA羽山秋人

Reputation: 150

You can try this:

for i in `pip list | awk -F ' ' '{print $1}'`; do pip install --upgrade $i; done

Upvotes: 15

Linus SEO
Linus SEO

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:

  • Replace 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.
  • Keep command simple and usable as many systems as possible.

Upvotes: 12

Alex V
Alex V

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
  1. pip list -o lists outdated packages;
  2. grep -v -i warning inverted match on warning to avoid errors when updating
  3. cut -f1 -d1' ' returns the first word - the name of the outdated package;
  4. tr "\n|\r" " " converts the multiline result from cut into a single-line, space-separated list;
  5. awk '{if(NR>=3)print}' skips header lines
  6. cut -d' ' -f1 fetches the first column
  7. xargs -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

SaxDaddy
SaxDaddy

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

snobb
snobb

Reputation: 1074

A JSON + jq answer:

pip list -o --format json | jq '.[] | .name' | xargs pip install -U

Upvotes: 8

Justin Lee
Justin Lee

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

Andy
Andy

Reputation: 2762

The below Windows cmd snippet does the following:

  • Upgrades pip to latest version.
  • Upgrades all outdated packages.
  • For each packages being upgraded checks 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

mcp
mcp

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

keypress
keypress

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

Elvin Jafarov
Elvin Jafarov

Reputation: 1467

pip freeze --local | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 pip install -U

Upvotes: -1

jfs
jfs

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

Related Questions