提问



是否可以使用 pip 一次升级所有Python包?[98]


请注意,官方问题跟踪器上有此功能请求。[99]

最佳参考


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


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


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


相关编辑:



  • 添加grep以跳过-e包定义,如@jawache所建议的(是的,您可以用sed或[[替换grep + cut 49]]或perl或......)。

  • 较新版本的pip允许您列出过时的包:


    pip list --outdated --format=freeze
    

  • 添加-n1xargs,如果更新一个包失败,则阻止停止所有内容(感谢@andsens)


其它参考1


您可以使用以下Python代码。与pip freeze不同,这不会打印警告和FIXME错误。


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)

其它参考2


升级所有本地包;你可以用pip-review:[101]


$ pip install pip-review
$ pip-review --local --interactive





pip-reviewpip-tools的分支。见@knedlsepp提到的pip-tools问题。 pip-review包装有效但pip-tools包装不再有效。[102]


pip-review自版本0.5开始在Windows上运行。

其它参考3


适用于Windows。对他人也应该有好处。
($是您在命令提示符下的任何目录。例如C:/Users/Username>)





$ pip freeze > requirements.txt


打开文本文件,用= =替换==


然后做


$ pip install -r requirements.txt --upgrade


如果某个程序包出现问题而导致升级失败(有时会出现问题),只需转到目录($),注释掉名称(在它之前添加#)并再次运行升级。您可以稍后取消注释该部分。这对于复制python全局环境也很有用。


我也喜欢pip-review方法:


py2
$ pip install pip-review

$ pip-review --local --interactive

py3
$ pip3 install pip-review

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


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

其它参考4


在浏览Rob van der Woude的FOR优秀文档之后的Windows版本[105]


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

其它参考5


您只需打印过时的软件包即可


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

其它参考6


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


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


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


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


| sed 's/^<First characters of the error>.*//'


这是一个工作示例:


pip list --format legacy --outdated | sed 's/(.*//g' | sed 's/^<First characters of the first error>.*//' | sed 's/^<First characters of the second error>.*//' | xargs pip install -U

其它参考7


这个选项在我看来更直接和可读:


pip install -U `pip list --outdated | awk '{ print $1}'`


(awk '{ print $1}'选择行的第一个单词(用空格分隔))


此版本允许从pip list --outdated中抑制警告消息:


pip install -U `pip list --outdated | awk '!/Could not|ignored/ { print $1}'`


(awk '!/<pattern>/'删除包含给定模式的行。在我的情况下,警告消息分别包括不能和忽略)


这也可用于解决即将出现的默认columns格式:


pip install -U `pip list --format=columns --outdated | awk '!/Package|---/{ print $1}'`

其它参考8


这似乎更简洁。


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


说明:


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


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


cut -d ' ' -f1中,-d ' '将space设置为分隔符,-f1表示获取第一列。


所以上面的行成为:


urllib3
wheel


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


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

其它参考9


来自https://github.com/cakebread/yolk:[106]


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


但是你需要先得到蛋黄:


$ sudo pip install -U yolk

其它参考10


更强大的解决方案


对于pip3使用此:


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


对于pip,只需删除3s:


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


OSX Oddity


截至2017年7月,OSX发布了一个非常旧版本的sed(十几岁)。要获得扩展的正则表达式,请在上面的解决方案中使用-E而不是-r。


解决热门解决方案的问题


该解决方案经过精心设计和测试 1 ,而即使是最流行的解决方案也存在问题。



  • 由于更改pip命令行功能而导致的可移植性问题

  • 因为常见的pip或pip3子进程失败而导致xargs崩溃

  • 从原始xargs输出拥挤记录

  • 依靠Python-to-OS桥接,同时可能升级它 3



上面的命令使用最简单,最便携的pip语法结合sed和sh来完全克服这些问题。可以使用注释版本 2 仔细检查sed操作的详细信息。





详情


pip freeze --local | grep -v '^\-e' | cut -d = -f 1  | xargs -n1 pip install -U
在Linux 4.8.16-200.fc24.x86_64集群中经过测试和定期使用,并在其他五种Linux/Unix版本上进行了测试。它还运行在Windows 10上安装的Cygwin64上。需要在iOS上进行测试。


pip list --outdated --format=freeze
为了更清楚地看到命令的解剖结构,这与带有注释的上述pip3命令完全相同:


# 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


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)
升级也用于升级Python或PIP组件的Python或PIP组件可能是导致死锁或程序包数据库损坏的潜在原因。

其它参考11


@Ramana答案的单行版本。


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


`

其它参考12


升级时遇到了同样的问题。事实是,我永远不会升级所有包裹。我只升级我需要的东西,因为项目可能会破坏。


因为没有简单的方法来升级逐包,并更新requirements.txt文件,我写了 pip-upgrader ,其中也更新了requirements.txt文件中的版本所选包裹(或所有包裹)。[108]


安装


pip install pip-upgrader


用法


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


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


pip-upgrade


高级用法


如果要求放在非标准位置,请将它们作为参数发送:


pip-upgrade path/to/requirements.txt


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


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


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


完全披露:我写了这个包。

其它参考13


当使用virtualenv并且如果您只想将添加包升级到virtualenv时,您可能希望:


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

其它参考14


你可以试试这个:


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

其它参考15


Windows Powershell解决方案


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

其它参考16


我在pip问题讨论中找到的最简单,最快速的解决方案是:[109]


sudo -H pip install pipdate
sudo -H pipdate


资料来源:https://github.com/pypa/pip/issues/3819 [110]

其它参考17


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


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


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


它可以做很多你可能会发现有用的东西。

其它参考18


通过拉动请求发送到pip民谣;在此期间使用我写的这个pip库解决方案:[112]


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

其它参考19


这似乎对我有用......


pip install -U $(pip list --outdated|awk '{printf $1" "}')


之后我用printf和空格来正确分离包名。

其它参考20


@Ramana的答案对我来说是最好的,在这里,但我不得不添加一些捕获:


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检查会排除我的开发包,因为它们不在系统的site-packages目录中。 try-except只是跳过从PyPI中删除的包。


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

其它参考21


我的剧本:


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

其它参考22


这不是更有效吗?


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列出过时的套餐;

  2. grep -v -i warningwarning上反向匹配以避免更新时出错

  3. cut -f1 -d1' '返回第一个单词 - 过时包的名称;

  4. tr "\n|\r" " "将多线结果从cut转换为单行,以空格分隔的列表;

  5. awk '{if(NR>=3)print}'跳过标题行

  6. cut -d' ' -f1获取第一列

  7. xargs -n1 pip install -U从其左边的管道中取出一个参数,并将其传递给命令以升级包列表。


其它参考23


使用awk更新包:
pip install -U $(pip freeze | awk -F'[=]' '{print $1}')

其它参考24


这是我对rbp的答案的变体,它绕过了可编辑和开发发行版。它分享了原始的两个缺陷:它不必要地重新下载和重新安装;并且一个包上的错误将阻止每个包的升级之后。


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


相关的错误报告,从bitbucket迁移后有点脱节:



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

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


其它参考25


我已经尝试了Ramana的代码,我在Ubuntu上发现你必须为每个命令写sudo。这是我的脚本在ubuntu 13.10上正常工作:[114] [115]


#!/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)

其它参考26


这是另一种在python中使用脚本的方法


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])

其它参考27


这是一个仅更新过期软件包的脚本。


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)

其它参考28


我最近一直在使用pur。它很简单而且非常重要。它会更新您的requirements.txt文件以反映升级,然后您可以像往常一样使用requirements.txt文件进行升级。[116]


$ 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 ...

其它参考29


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


甚至:


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


快速工作,因为它不会不断发布shell。我很想找到时间来实际使用过时的列表来加快速度。