如何使用 pip 升级所有 Python 包

Posted

技术标签:

【中文标题】如何使用 pip 升级所有 Python 包【英文标题】:How to upgrade all Python packages with pip 【发布时间】:2011-02-12 18:47:59 【问题描述】:

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

注意:官方问题跟踪器上有a feature request。

【问题讨论】:

当心software rot——升级依赖可能会破坏你的应用。您可以使用pip freeze(如bundle installnpm shrinkwrap)列出所有已安装软件包的确切版本。最好在修补之前保存一份副本。 如果你想更新单个包和所有 its 依赖项(可以说是一种更明智的方法),请执行以下操作: pip install -U --upgrade-strategy -包 我使用 PowerShell 7,目前我使用这个单行代码:pip list --format freeze | %pip install --upgrade $_.split('==')[0](我还无法在此处发布答案) 【参考方案1】:

以下内容适用于 Windows,对其他人也应该有好处($ 是您所在的目录,在命令提示符中。例如,C:/Users/Username)。

$ pip freeze > requirements.txt

打开文本文件,将 == 替换为 >=,或者让 sed 为您完成:

$ sed -i 's/==/>=/g' requirements.txt

并执行:

$ pip install -r requirements.txt --upgrade

如果您遇到某个软件包停止升级的问题(有时是NumPy),只需转到目录($),注释掉名称(在其前添加#)并再次运行升级。您可以稍后取消注释该部分。这对于复制 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”来升级所有软件包;如果一次升级失败,请再次运行它并在下一次继续。

【讨论】:

你应该删除requirements.txt==version。例如:python-dateutil==2.4.2python-dateutil 对于所有行。 我发现这并没有真正升级macOS上的包。 @youngminz 在运行“pip install...”之前,我会建议在编辑器/ide 中快速“替换所有“==”>“>=”来解决此问题 for linux: $ pip freeze | cut -d '=' -f1> requirements.txt 删除版本 如果你使用的shell是bash,你可以通过pip3 install -r <(pip3 freeze) --upgrade将其缩短为一个命令实际上<(pip3 freeze)是一个匿名管道,但它会充当一个文件对象【参考方案2】:

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

(点 > 20.0)

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

旧版本:

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

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

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

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

这是一个工作示例:

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

【讨论】:

不得不为以 'Could' 和 'Some' 开头的行添加过滤器,因为显然 pip 会向标准输出发送警告 :( 好的,这很公平:您可以根据需要添加任意数量的| sed 's/^&lt;First characters of the error&gt;.*//'。谢谢! 或:pip list --outdated | cut -d ' ' -f 1 | xargs -n 1 pip install --upgrade【参考方案3】:

pip_upgrade_outdated(基于this older script)完成了这项工作。根据its documentation:

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 步:

pip install pip-upgrade-outdated

第 2 步:

pip_upgrade_outdated

【讨论】:

第 1 步:pip install pip-upgrade-outdated 第 2 步:pip-upgrade-outdated ...完成 这确实是一个非常好的包。需要更多宣传,我在 python 中工作了很长时间,这是我第一次听说它。不错! @MarioChapa 谢谢——我写的(基于要点)。 在 windows 中,%USERPROFILE%\anaconda3\envs\bridge\scripts\pip_upgrade_outdated.exe【参考方案4】:

在 Windows 或 Linux 上更新 Python 包

1-将已安装包的列表输出到需求文件(requirements.txt)中:

pip freeze > requirements.txt

2- 编辑 requirements.txt,并将所有“==”替换为“>=”。使用编辑器中的“全部替换”命令。

3 - 升级所有过时的包

pip install -r requirements.txt --upgrade

来源:https://www.activestate.com/resources/quick-reads/how-to-update-all-python-packages/

【讨论】:

这行得通。之后只需执行pip freeze &gt; requirements.txt 即可查看实际差异。 pip freeze | sed 's/==/&gt;=/' &gt; requirements.txt 自动将==&gt;= 交换。【参考方案5】:

更强大的解决方案

对于 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

OS X 奇怪

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

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

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

由于更改 pip 命令行功能导致的可移植性问题 xargs 因常见 pip 或 pip3 子进程故障而崩溃 来自原始 xargs 输出的拥挤日志记录 依赖 Python 到操作系统的桥,同时可能会升级它3

上面的命令使用最简单和最便携的pip语法结合sedsh来彻底解决这些问题。 sed 操作的细节可以用注释版本2仔细检查。


详情

[1] 在 Linux 4.8.16-200.fc24.x86_64 集群中经过测试并经常使用,并在其他五种 Linux/Unix 版本上进行了测试。它还可以在 Windows 10 上安装的 Cygwin64 上运行。需要在 ios 上进行测试。

[2] 为了更清楚地查看命令的结构,这与上面带有 cmets 的 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

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

【讨论】:

克服 OS X 侏罗纪 BSD sed 的另一种方法是改用 gsed (GNU sed)。要得到它,brew install gnu-sed @WalterTross ...侏罗纪...很好的形容词使用。因此,我们现在有两种方法可以在终端上通过良好的审计跟踪对更新 pip 包进行分组。 (1)使用答案中的 -E 选项和(2)安装 gsed 以离开侏罗纪。【参考方案6】:

要升级默认 python 版本中的所有 pip 默认包,只需在终端或命令提示符下运行底部 python 代码:

import subprocess
import re


pkg_list = subprocess.getoutput('pip freeze')

pkg_list = pkg_list.split('\n')


new_pkg = []
for i in pkg_list:
    re.findall(r"^(.*)==.*", str(i))
    new = re.findall(r"^(.*)==.*", str(i))[0]
    new_pkg.append(new)

for i in new_pkg:
    print(subprocess.getoutput('pip install '+str(i)+' --upgrade'))

【讨论】:

【参考方案7】:

在 bat 脚本中

call pip freeze > requirements.txt
call powershell "(Get-Content requirements.txt) | ForEach-Object  $_ -replace '==', '>='  | Set-Content requirements.txt"
call pip install -r requirements.txt --upgrade

【讨论】:

【参考方案8】:

一个纯粹的Bash/Z shell 实现这一目标:

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

或者,以一种格式良好的方式:

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

【讨论】:

代表什么?

@ᐅdevrimbaris 这将删除版本规范并仅保留包名称。你可以通过运行for p in $(pip list -o --format freeze); do echo "$p -&gt; $p%%=*"; done 来查看它。更一般地说,$haystack%%needle 表示delete longest match of needle from back of haystack【参考方案9】:

这是通过 pip 更新所有 Python 3 包(在激活的virtualenv 中)的代码:

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)

【讨论】:

【参考方案10】:

一个 JSON + jq 答案:

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

【讨论】:

【参考方案11】:

使用pipupgrade!

$ pip install pipupgrade
$ pipupgrade --verbose --latest --yes

pipupgrade 帮助您从requirements.txt 文件升级您的系统、本地或软件包!它还选择性地升级不会破坏更改的软件包。

pipupgrade 还确保升级存在于多个 Python 环境中的包。它与 Python 2.7+、Python 3.4+ 和 pip 9+、pip 10+、pip 18+、pip 19+ 兼容。

注意:我是该工具的作者。

【讨论】:

这个方法的输出比@rbp 的回答干净得多 好主意,但是当我尝试它时它永远停留在Checking... 刚安装完还卡在检查[0;93mChecking...[0m 在 Windows 10 和 Python 3.7.5 上出现错误:ModuleNotFoundError: No module named 'ctypes.windll' 好像有些问题:Checking... 2020-03-16 11:37:03,587 | WARNING | Unable to save package name. UNIQUE constraint failed: tabPackage.name 2020-03-16 11:37:13,604 | WARNING | Unable to save package name. database is locked 2020-03-16 11:37:13,609 | WARNING | Unable to save package name. database is locked【参考方案12】:

PowerShell 5.1 中的一行,具有管理员权限,Python 3.6.5 和 pip 版本 10.0.1:

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

如果列表中没有破损的包裹或特殊的***,它可以正常工作...

【讨论】:

出于纯粹的审美原因,我最喜欢这种方法。生成输出的可执行文件为我们的 shell 提供对象模式,并且脚本中不需要未标记的索引值 [0]【参考方案13】:

使用AWK更新包:

pip install -U $(pip freeze | awk -F'[=]' 'print $1')

Windows PowerShell 更新

foreach($p in $(pip freeze)) pip install -U $p.Split("=")[0]

【讨论】:

对于 python 3... pip3 install -U $(pip3 freeze | awk -F'[=]' 'print $1')【参考方案14】:

正如这里的另一个答案所说:

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

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

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

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

【讨论】:

在为整个系统更新软件包时使用带有虚拟环境的第一个版本和第二个 (sudo -H) 版本。【参考方案15】:

用途:

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

【讨论】:

【参考方案16】:

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

因为没有简单的方法来逐包升级和更新 requirements.txt 文件,我写了这个pip-upgrader,它也更新了你的requirements.txt文件中的版本选择(或所有包)。

安装

pip install pip-upgrader

用法

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

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

pip-upgrade

高级用法

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

pip-upgrade path/to/requirements.txt

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

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

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

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

【讨论】:

这是 pip 默认应该做的。 提醒您的工具,一些字符转义似乎在我的 Windows 机器上无法正常工作,但除此之外没问题 还没有真正在 Windows 上测试过,但我会安装一个虚拟机。谢谢 如果virtualenv 未启用pip-upgrade --skip-virtualenv-check 这也适用于具有 common、dev 和 prod 需求的需求文件夹。简直太棒了!【参考方案17】:
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's answer 并使其对 pip3 友好。

【讨论】:

【参考方案18】:

用途:

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。

【讨论】:

当我们最终从 pypi 下载包然后(编译和)安装时,不断启动 shell 真的会产生可衡量的不同吗? @gerrit 我的经验是,确实如此,尤其是在您拥有无法关闭运行的激进防病毒软件的环境中。在我工作的地方,我们无法禁用或抑制 AV,每次 shell 启动需要 20-30 秒,但在好的日子里,我们确实有快速的互联网连接。当您安装大包时,安装时间可能很长,但当安装很多较小的包时,shell 启动时间非常重要。【参考方案19】:

这是一个只更新过时软件包的脚本。

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+):

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)

【讨论】:

遗憾的是,这不再有效。 pip --format 不接受“旧版”作为选择。至少在我的 python 版本中没有。 @Rocketq 这是多么错误的做法,它的作用与该线程中的 50-100 个其他示例完全一样。我认为你是一个巨魔,因为更新 python 包不会破坏你的电脑 @StormShadow 正如你所希望的那样,pip 对依赖关系的控制真的很差。它与其他解决方案完全一样 - 是的((最好添加免责声明【参考方案20】:

Windows PowerShell 解决方案

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

【讨论】:

pip list --outdated | %$_.split('==')[0] | %pip install --upgrade $_? 或许pip list --outdated --format freeze | %$_.split('==')[0] | %pip install --upgrade $_ 更合适。 为什么pip list --outdated --format freeze.. 比 Powershell 中建议的答案更受欢迎,@brainplot @Timo 当我写该评论时,建议的答案仅使用pip list 而不是pip freeze。我认为--format freeze 会比让pip list 决定格式更能抵御未来更新中可能发生的变化。 pip freeze 也可以!【参考方案21】:

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

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

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

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

【讨论】:

你的答案已经从yolk改成了yolk3k,你原来的答案肯定是python3有问题。【参考方案22】:

这是在 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])

【讨论】:

【参考方案23】:

这似乎对我有用...

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

我使用printf 和一个空格来正确分隔包名。

【讨论】:

【参考方案24】:

这样应该更有效:

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 列出过时的软件包; grep -v -i warning 反向匹配 warning 以避免更新时出错 cut -f1 -d1' ' 返回第一个单词——过期包的名称; tr "\n|\r" " " 将来自 cut 的多行结果转换为以空格分隔的单行列表; awk 'if(NR&gt;=3)print' 跳过标题行 cut -d' ' -f1 获取第一列 xargs -n1 pip install -U 从它左边的管道中获取 1 个参数,并将其传递给命令以升级包列表。

【讨论】:

这是我的输出:kerberos iwlib PyYAML Could pygpgme Could Could Could ... 请注意所有“可能”。这些来自pip list -o 的输出“找不到任何满足要求的下载 你能粘贴pip list -o的输出吗? 评论的格式不太好,但是这里有一个 sn-p(行尾标有';'):# pip list -o; urwid (Current: 1.1.1 Latest: 1.3.0); Could not find any downloads that satisfy the requirement python-default-encoding; pycups (Current: 1.9.63 Latest: 1.9.68); Could not find any downloads that satisfy the requirement policycoreutils-default-encoding; Could not find any downloads that satisfy the requirement sepolicy; 我建议不要过滤掉所有不应该使用的行,而是过滤存在更新的行:pip install -U $(pip list -o | grep -i current | cut -f1 -d' ' | tr "\n|\r" " ") 。否则你很容易错过你不想要的一行并得到 DrStrangeprk 提到的结果。 我强烈建议改用xargspip list -o | awk '/Current:/ print $1' | xargs -rp -- pip install -U -r 标志确保pip install -U 在没有过期包的情况下不会运行。 -p 标志提示用户在执行任何命令之前进行确认。您可以添加 -n1 标志,以便在单独安装每个软件包之前提示您。【参考方案25】:

我试过the code of Ramana,我发现在Ubuntu上你必须为每个命令写sudo。这是我的脚本,在 Ubuntu 13.10 (Saucy Salamander) 上运行良好:

#!/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】:

通过a pull-request to the pip folks发送;同时使用我写的这个 pip 库解决方案:

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

【讨论】:

带错误处理的版本(根据评论):gist.github.com/SamuelMarks/7885f2e8e5f0562b1063【参考方案27】:

你可以试试这个:

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

【讨论】:

这是以最简洁的方式更新 pip 包的最简洁、可读性最高的方法。很棒。【参考方案28】:

Ramana's answer 的单行版本。

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

【讨论】:

subprocess.call("sudo pip install... 以防您需要权限 @MaximilianoRios 请不要使用sudo pip install,而是使用virtual env。【参考方案29】:

Ramana's answer 对我来说是最适合我的,这里的那些,但我必须添加一些问题:

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

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

【讨论】:

在 Ubuntu(和其他 Debian 衍生产品)上,pip 显然将软件包放在 /usr/local/lib/python2.7/dist-packages 或类似的位置。在这种情况下,您可以在 if 语句中使用 '/usr/local/lib/' 而不是 'site-packages'。【参考方案30】:

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

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

但是,你需要先得到蛋黄:

$ sudo pip install -U yolk

【讨论】:

最后一次提交 7 年前 公元 2013 年

以上是关于如何使用 pip 升级所有 Python 包的主要内容,如果未能解决你的问题,请参考以下文章

python 如何PIP批量升级所有旧的python包

使用 pip 命令从 requirements.txt 升级 python 包

如何升级python 版本

如何在 AWS Lambda 中使用 Python 自定义包

APP store如何升级所有的app

Python: 使用pip升级所有包