关于python:使用pip升级所有包

 2019-04-23 

Upgrading all packages with pip

是否可以使用pip一次性升级所有python包?

请注意,官方问题跟踪程序对此有一个功能请求。


还没有内置标志,但您可以使用

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

注:这有无限的潜在变化。我试图保持这个答案简短,但请在评论中提出不同的建议!

在旧版本的pip中,您可以使用它来代替:

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

grep将跳过@jawache建议的可编辑("-e")包定义。(是的,您可以用sedawkperl或……替换grepcut

xargs-n1标志防止在更新一个包失败时停止所有操作(谢谢@andsens)。


您可以使用下面的python代码。与pip freeze不同,它不会打印警告和修复错误。对于pip<10.0.1

1
2
3
4
5
import pip
from subprocess import call

packages = [dist.project_name for dist in pip.get_installed_distributions()]
call("pip install --upgrade" + ' '.join(packages), shell=True)

对于pip>=10.0.1

1
2
3
4
5
import pkg_resources
from subprocess import call

packages = [dist.project_name for dist in pkg_resources.working_set]
call("pip install --upgrade" + ' '.join(packages), shell=True)


要升级所有本地软件包,可以使用pip-review

1
2
$ pip install pip-review
$ pip-review --local --interactive

pip-reviewpip-tools的分叉。见@knedlsepp提及的pip-tools期。pip-review包工作,但pip-tools包不再工作。

pip-review从0.5版开始就在Windows上工作。


Works on Windows. Should be good for others too.
($ is whatever directory you're in, in command prompt. eg. C:/Users/Username>)

do

1
$ pip freeze > requirements.txt

打开文本文件,将==替换为>。=

然后做

1
$ pip install -r requirements.txt --upgrade

如果您在某个包暂停升级时遇到问题(有时是numpy),只需转到目录($),注释掉名称(在名称之前添加一个),然后再次运行升级。稍后可以取消对该节的注释。这对于复制python全局环境也是很好的。

我也喜欢PIP审查方法:

1
2
3
4
5
6
7
8
9
py2
$ pip install pip-review

$ pip-review --local --interactive

py3
$ pip3 install pip-review

$ py -3 -m pip_review --local --interactive

您可以选择"a"来升级所有包;如果一次升级失败,请再次运行它,然后在下一次升级时继续。


Windows版本,参考了Rob van der Woude为FOR编写的优秀文档

1
for /F"delims===" %i in ('pip freeze -l') do pip install -U %i


你只需打印那些过时的包裹

1
pip freeze | cut -d = -f 1 | xargs -n 1 pip search | grep -B2 'LATEST:'


以下一行可能会有所帮助:

pip list --format freeze --outdated | sed 's/(.*//g' | xargs -n1 pip install -U

如果发生错误,xargs -n1将继续运行。

如果您需要对省略的内容和引发错误的内容进行更多的"细粒度"控制,则不应添加-n1标志,并通过"管道"为每个单独的错误明确定义要忽略的错误:

| sed 's/^.*//'

下面是一个工作示例:

1
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


在我看来,这个选项更简单易读:

1
pip install -U `pip list --outdated | tail -n +3 | awk '{print $1}'`

解释是,pip list --outdated以这种格式输出所有过时软件包的列表:

1
2
3
4
5
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

tail -n +3跳过前两行,awk '{print $1}'选择每行的第一个字。


这似乎更简洁了。

1
pip list --outdated | cut -d ' ' -f1 | xargs -n1 pip install -U

说明:

pip list --outdated得到这样的线条

1
2
urllib3 (1.7.1) - Latest: 1.15.1 [wheel]
wheel (0.24.0) - Latest: 0.29.0 [wheel]

cut -d ' ' -f1中,-d ' '设置"空格"作为分隔符,-f1表示得到第一列。

所以上面的行变成:

1
2
urllib3
wheel

然后把它们传给xargs运行命令pip install -U,每行作为附加参数

-n1将传递给每个命令的参数数目pip install -U限制为1。


使用PiPopePosig!

1
2
$ pip install pipupgrade
$ pipupgrade --latest --yes

pipupgrade帮助您从requirements.txt文件升级系统、本地或软件包!它还选择性地升级那些不会破坏变化的包。与python2.7+、python3.4+和pip9+、pip10+、pip18+兼容。

enter image description here

注意:我是这个工具的作者。


更强大的解决方案

对于PIP3,请使用:

1
pip3 freeze --local |sed -rn 's/^([^=# \t\\][^ \t=]*)=.*/echo; echo Processing \1 ...; pip3 install -U \1/p' |sh

对于PIP,只需移除3S即可:

1
pip freeze --local |sed -rn 's/^([^=# \t\\][^ \t=]*)=.*/echo; echo Processing \1 ...; pip install -U \1/p' |sh

OSX奇异性

截至2017年7月,OSX推出了非常老的SED版本(12年前)。要获得扩展正则表达式,请在上面的解决方案中使用-e而不是-r。

用流行的解决方案解决问题

这个解决方案设计和测试都很好,但是即使是最流行的解决方案也存在问题。

  • 由于更改PIP命令行功能而导致的可移植性问题
  • 由于常见的PIP或PIP3子进程失败而导致xargs崩溃
  • 原始xargs输出的密集日志记录
  • 依赖python-to-os桥,同时可能升级it3

上面的命令使用最简单和最可移植的PIP语法结合SED和SH来完全解决这些问题。SED操作的细节可以通过注释版本2进行审查。

细节

[1]在Linux 4.8.16-200.fc24.x86_64集群中测试并定期使用,并在其他五种Linux/Unix风格上进行测试。它还运行在安装在Windows10上的cygwin64上。需要在iOS上进行测试。

[2]要更清楚地看到命令的解剖结构,这与上面的pip3命令(带有注释)完全相同:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# match lines from pip's local package list output
# that meet the following three criteria and pass the
# package name to the replacement string in group 1.
# (a) Do not start with invalid characters
# (b) Follow the rule of no white space in the package names
# (c) Immediately follow the package name with an equal sign
sed="s/^([^=# \t\\][^ \t=]*)=.*"

# separate the output of package upgrades with a blank line
sed="$sed/echo"

# indicate what package is being processed
sed="$sed; echo Processing \1 ..."

# perform the upgrade using just the valid package name
sed="$sed; pip3 install -U \1"

# output the commands
sed="$sed/p"

# stream edit the list as above
# and pass the commands to a shell
pip3 freeze --local |sed -rn"$sed" |sh

[3]升级也用于升级python或pip组件的python或pip组件可能是死锁或包数据库损坏的潜在原因。


我在升级方面也有同样的问题。问题是,我从不升级所有软件包。我只升级我需要的,因为项目可能会中断。

因为没有简单的方法来逐个包升级和更新requirements.txt文件,所以我编写了这个pip升级程序,它还为所选包(或所有包)更新了requirements.txt文件中的版本。

安装

1
pip install pip-upgrader

用法

激活virtualenv(这一点很重要,因为它还将在当前virtualenv中安装升级包的新版本)。

cd进入项目目录,然后运行:

1
pip-upgrade

高级用法

如果需求放置在非标准位置,则将其作为参数发送:

1
pip-upgrade path/to/requirements.txt

如果您已经知道要升级哪个包,只需将它们作为参数发送:

1
pip-upgrade -p django -p celery -p dateutil

如果需要升级到预发布/发布后版本,请在命令中添加--prerelease参数。

完全公开:我写了这个包裹。


来自https://github.com/cakebread/yolk:

1
$ pip install -U `yolk -U | awk '{print $1}' | uniq`

然而,你需要先得到蛋黄:

1
$ sudo pip install -U yolk

一个线性版本的@ramana的答案。

1
python -c 'import pip, subprocess; [subprocess.call("pip install -U" + d.project_name, shell=1) for d in pip.get_installed_distributions()]'

`


Windows PowerShell解决方案

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

使用virtualenv时,如果您只想升级添加到virtualenv中的包,那么您可能需要执行以下操作:

1
pip install `pip freeze -l | cut --fields=1 -d = -` --upgrade

我在PIP问题讨论中发现的最简单和最快速的解决方案是:

1
2
sudo -H pip install pipdate
sudo -H pipdate

来源:https://github.com/pypa/pip/issues/3819


相当神奇的蛋黄使这很容易。

1
2
pip install yolk3k # don't install `yolk`, see https://github.com/cakebread/yolk/issues/35
yolk --upgrade

有关York的更多信息:https://pypi.python.org/pypi/yolk/0.4.3

它可以做很多你可能会觉得有用的事情。


您可以尝试以下操作:

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


@拉玛娜的回答对我和这里的人都是最有效的,但我不得不添加一些捕获物:

1
2
3
4
5
6
7
import pip
for dist in pip.get_installed_distributions():
    if 'site-packages' in dist.location:
        try:
            pip.call_subprocess(['pip', 'install', '-U', dist.key])
        except Exception, exc:
            print exc

site-packages检查不包括我的开发包,因为它们不在系统站点包目录中。除了跳过已经从pypi中删除的包之外,尝试。

@endolith:我也希望有一个简单的pip.install(dist.key, upgrade=True),但它看起来不像是要被命令行以外的任何东西使用(docs没有提到内部API,而pip开发人员没有使用docstrings)。


这似乎对我有用…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
pip install -U $(pip list --outdated|awk '{printf $1"
<hr><P>使用awk更新包:<wyn>
pip install -U $(pip freeze | awk -F'
[=]' '{print $1}')
</wyn></P><P>Windows PowerShell更新<wyn>
foreach($p in $(pip freeze)){ pip install -U $p.Split("=")[0]}
</wyn></P><div class="suo-content">[collapse title=""]<ul><li>pip冻结awk-f'
[=]''打印$1'xargs pip安装-u</li><li>对于python 3…pip3安装-u$(pip3冻结awk-f'[=]''打印$1')</li></ul>[/collapse]</div><hr><P>通过拉请求发送给pip-folk;同时使用我写的这个pip库解决方案:</P>[cc lang="python"]from pip import get_installed_distributions
from pip.commands import install

install_cmd = install.InstallCommand()

options, args = install_cmd.parse_args([package.project_name
                                        for package in
                                        get_installed_distributions()])

options.upgrade = True
install_cmd.run(options, args)  # Chuck this in a try/except and print as wanted


这不是更有效吗?

1
2
pip3 list -o | grep -v -i warning | cut -f1 -d' ' | tr"""
" | awk '{if(NR>=3)print}' | cut -d' ' -f1 | xargs -n1 pip3 install -U
  • pip list -o列出了过时的包装;
  • grep -v -i warningwarning上的倒置匹配,以避免更新时出错。
  • cut -f1 -d1' '返回第一个字—过时包的名称;
  • tr"
    |
    """
    cut的多行结果转换成一个单行、空格分隔的列表;
  • awk '{if(NR>=3)print}'跳过标题行
  • cut -d' ' -f1取第一列
  • xargs -n1 pip install -U从其左边的管道中获取1个参数,并将其传递给命令以升级包列表。

  • 我的剧本:

    1
    pip list --outdated --format=legacy | cut -d ' ' -f1 | xargs -n1 pip install --upgrade

    最短最简单的窗户。

    1
    pip freeze > requirements.txt && pip install --upgrade -r requirements.txt && rm requirements.txt


    怎么样:

    1
    pip install -r <(pip freeze) --upgrade

    PowerShell 5.1中的一行,具有adm权限,python 3.6.5和pip版本10.0.1:

    1
    pip list -o --format json | ConvertFrom-Json | foreach {pip install $_.name -U --no-warn-script-location}

    如果列表中没有损坏的包裹或特殊的轮子,它就可以顺利工作…


    pip_upgrade_outdated负责。根据其文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    usage: pip_upgrade_outdated [-h] [-3 | -2 | --pip_cmd PIP_CMD]
                                [--serial | --parallel] [--dry_run] [--verbose]
                                [--version]

    Upgrade outdated python packages with pip.

    optional arguments:
      -h, --help         show this help message and exit
      -3                 use pip3
      -2                 use pip2
      --pip_cmd PIP_CMD  use PIP_CMD (default pip)
      --serial, -s       upgrade in serial (default)
      --parallel, -p     upgrade in parallel
      --dry_run, -n      get list, but don't upgrade
      --verbose, -v      may be specified multiple times
      --version          show program'
    s version number and exit

    步骤1:

    1
    pip install pip-upgrade-outdated

    步骤2:

    1
    pip_upgrade_outdated


    1
    2
    3
    4
    import pip
    pkgs = [p.key for p in pip.get_installed_distributions()]
    for pkg in pkgs:
        pip.main(['install', '--upgrade', pkg])

    甚至:

    1
    2
    3
    4
    import pip
    commands = ['install', '--upgrade']
    pkgs = commands.extend([p.key for p in pip.get_installed_distributions()])
    pip.main(commands)

    工作速度很快,因为它不经常发射炮弹。我很想找时间用过时的列表来加快速度。


    下面是我对RBP答案的修改,它绕过了"可编辑"和开发分布。它共享了原版的两个缺陷:不必要地重新下载和重新安装;一个包上的错误将阻止此后每个包的升级。

    1
    pip freeze |sed -ne 's/==.*//p' |xargs pip install -U --

    相关的bug报告,从bitback迁移后有点脱节:

    • https://github.com/pypa/pip/issues/49
    • https://github.com/pypa/pip/issues/59

    查看所有过时的包

    1
     pip list --outdated --format=columns

    安装

    1
     sudo pip install pipdate

    然后类型

    1
     sudo -H pipdate

    我试过Ramana的代码,发现在Ubuntu上,你必须为每个命令编写sudo。这是我在Ubuntu 13.10上运行良好的脚本:

    1
    2
    3
    4
    5
    6
    #!/usr/bin/env python
    import pip
    from subprocess import call

    for dist in pip.get_installed_distributions():
        call("sudo pip install --upgrade" + dist.project_name, shell=True)

    这是针对python 3的PowerShell解决方案:

    1
    pip3 list --outdated --format=legacy | ForEach { pip3 install -U $_.split("")[0] }

    对于python 2:

    1
    pip2 list --outdated --format=legacy | ForEach { pip2 install -U $_.split("")[0] }

    这将逐个升级包。所以A

    1
    2
    pip3 check
    pip2 check

    然后应该确保没有破坏依赖关系。


    下面是一个只更新过时包的脚本。

    1
    2
    3
    4
    5
    6
    7
    8
    import os, sys
    from subprocess import check_output, call

    file = check_output(["pip.exe", "list","--outdated","--format=legacy"])
    line = str(file).split()

    for distro in line[::6]:
        call("pip install --upgrade" + distro, shell=True)

    对于不作为旧格式输出的新版本PIP(版本18+)。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    import os, sys
    from subprocess import check_output, call

    file = check_output(["pip.exe", "list","-o","--format=json"])
    line = str(file).split()

    for distro in line[1::8]:
        distro = str(distro).strip('"",')
        call("pip install --upgrade" + distro, shell=True)


    下面是另一种处理Python中脚本的方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import pip, tempfile, contextlib

    with tempfile.TemporaryFile('w+') as temp:
        with contextlib.redirect_stdout(temp):
            pip.main(['list','-o'])
        temp.seek(0)
        for line in temp:
            pk = line.split()[0]
            print('--> updating',pk,'<--')
            pip.main(['install','-U',pk])

    我最近一直在用聚氨酯。这很简单,而且切中要害。它会更新您的requirements.txt文件以反映升级情况,然后您可以像往常一样使用requirements.txt文件进行升级。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    $ pip install pur
    ...
    Successfully installed pur-4.0.1

    $ pur
    Updated boto3: 1.4.2 -> 1.4.4
    Updated Django: 1.10.4 -> 1.10.5
    Updated django-bootstrap3: 7.1.0 -> 8.1.0
    All requirements up-to-date.

    $ pip install --upgrade -r requirements.txt
    Successfully installed Django-1.10.5 ...

    命令中的一行:

    1
    for /F"delims=" %i in ('pip list --outdated --format=legacy') do pip install -U %i

    所以A

    pip check

    然后应该确保没有破坏依赖关系。


    以下是我的变体:

    1
    pip list --outdated --format=legacy | awk '{print $1;}' | xargs -n1 pip install -U

    另一个答案是:

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

    是一个可能的解决方案,这里的一些评论(包括我自己)在使用此命令时遇到了权限问题。对以下内容稍作改动,就为我解决了这些问题。

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

    注意添加的sudo-h,它允许命令以根权限运行。


    还有另一种方式:以东十一〔十三〕。


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    import os
    import pip
    from subprocess import call, check_call

    pip_check_list = ['pip', 'pip3']
    pip_list = []
    FNULL = open(os.devnull, 'w')


    for s_pip in pip_check_list:
        try:
            check_call([s_pip, '-h'], stdout=FNULL)
            pip_list.append(s_pip)
        except FileNotFoundError:
            pass


    for dist in pip.get_installed_distributions():
        for pip in pip_list:
            call("{0} install --upgrade".format(pip) + dist.project_name, shell=True)

    我接受了@ramana的回答,让它对pip3友好。


    纯bash/zsh oneliner可以做到:

    1
    for p in $(pip list -o --format freeze); do pip install -U ${p%%=*}; done

    或者,以良好的格式:

    1
    2
    3
    4
    for p in $(pip list -o --format freeze)
    do
        pip install -U ${p%%=*}
    done

    1
    pip list -o | cut -d' ' -f1 | xargs -n1 pip install -U 2> /dev/null

    如果您有两个不同版本的python,并且只想升级所有python3的包,那么只需键入pip3,而不是pip

    2> /dev/null用于消除所有恼人的错误信息。


    我能找到的最短最简单的:

    1
    pip install -U $(pip freeze | cut -d"=" -f1)

    $(cmd)键允许您包装任何shell命令行(它返回其输出)。


    只需为记录添加json+jq答案:

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

    更新所有已安装软件包的快捷方法是:

    1
    for pkg in $(pip list | cut -d' ' -f1) ; do pip install $pkg -U ; done

    即使在Conda环境中也能工作的最佳解决方案是:

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

    1
    python -c 'import pip; [pip.main(["install","--upgrade", d.project_name]) for d in pip.get_installed_distributions()]'

    一班轮!


  • 首先安装JQ(Mac):

    $BREW安装JQ

  • 2。

    1
    $pip3 install --upgrade  `pip3 list --outdated --format json | jq '.[] | .name' | awk -F'"' '{print $2}'`

    如果您只希望升级由pip安装的软件包,并且为了避免升级由其他工具(如apt、yum等)安装的软件包,那么您可以使用我在我的Ubuntu上使用的这个脚本(也可以在其他发行版上使用),基于以下文章:

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

    1
    pip list | awk -F ' ' '{print $1}' | xargs -l pip install --upgrade