是否可以一次升级所有 Python 包pip
?
注意:官方问题跟踪器上有一个功能请求。
还没有内置标志,但您可以使用
pip list --outdated --format=freeze | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 pip install -U
注意:这有无限的潜在变化。我试图让这个答案简短而简单,但请在评论中提出变化!
在旧版本的 中pip
,您可以改用它:
pip freeze --local | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 pip install -U
这grep
是跳过可编辑(“-e”)包定义,正如@jawache 所建议的那样。(是的,您可以将grep
+cut
替换为sed
orawk
或perl
or ...)。
如果更新一个包失败,该-n1
标志xargs
防止停止一切(感谢@andsens)。
您可以使用以下 Python 代码。与 不同pip freeze
,这不会打印警告和 FIXME 错误。
对于点 < 10.0.1
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)
对于点 >= 10.0.1
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
:
$ pip install pip-review
$ pip-review --local --interactive
pip-review
是 的一个叉子pip-tools
。请参阅pip-tools
@knedlsepp提到的问题。pip-review
包工作,但pip-tools
包不再工作。
pip-review
从 0.5 版开始在 Windows 上工作。
以下适用于 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”来升级所有软件包;如果一次升级失败,请再次运行它并在下一次继续。
$ 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+ 兼容。
注意:我是该工具的作者。
在查阅Rob van der Woude的优秀文档FOR
后的 Windows 版本:
for /F "delims===" %i in ('pip freeze') do pip install --upgrade %i
这个选项在我看来更直接和可读:
pip install -U `pip list --outdated | awk 'NR>2 {print $1}'`
解释是以pip list --outdated
这种格式输出所有过时包的列表:
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
在 awk 命令中,NR>2
跳过前两条记录(行)并{print $1}
选择每行的第一个单词(正如 SergioAraujo 所建议的,我删除了tail -n +3
因为awk
确实可以处理跳过记录)。
您可以只打印过时的包:
pip freeze | cut -d = -f 1 | xargs -n 1 pip search | grep -B2 'LATEST:'
以下单线可能会有所帮助:
(点 > 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
更强大的解决方案
对于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语法结合sed和sh来完全克服这些问题。sed操作的细节可以用注释版本2仔细检查。
细节
[1] 在 Linux 4.8.16-200.fc24.x86_64 集群中测试并定期使用,并在其他五种 Linux/Unix 版本上进行测试。它还可以在 Windows 10 上安装的 Cygwin64 上运行。需要在 iOS 上进行测试。
[2] 为了更清楚地了解命令的结构,这与上面的 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 组件可能是导致死锁或包数据库损坏的潜在原因。
这似乎更简洁。
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 ' '
设置“空格”为分隔符,-f1
表示获取第一列。
所以上面的行变成:
urllib3
wheel
然后将它们传递给以xargs
运行命令,pip install -U
每行作为附加参数
-n1
将传递给每个命令的参数数量限制pip install -U
为 1
我在升级时遇到了同样的问题。问题是,我从不升级所有软件包。我只升级我需要的东西,因为项目可能会中断。
因为没有简单的方法来逐个升级包并更新 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
请在命令中添加参数。
完全披露:我写了这个包。
拉马纳答案的单行版本。
python -c 'import pip, subprocess; [subprocess.call("pip install -U " + d.project_name, shell=1) for d in pip.get_installed_distributions()]'
来自https://github.com/cakebread/yolk:
$ pip install -U `yolk -U | awk '{print $1}' | uniq`
但是,你需要先得到蛋黄:
$ sudo pip install -U yolk
使用virtualenv时,如果您只想升级添加到 virtualenv 的软件包,您可能需要执行以下操作:
pip install `pip freeze -l | cut --fields=1 -d = -` --upgrade
pip_upgrade_outdated
(基于这个较旧的脚本)可以完成这项工作。根据其文档:
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
pip freeze | %{$_.split('==')[0]} | %{pip install --upgrade $_}
使用AWK更新包:
pip install -U $(pip freeze | awk -F'[=]' '{print $1}')
Windows PowerShell更新
foreach($p in $(pip freeze)){ pip install -U $p.Split("=")[0]}
在 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/
具有管理员权限的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}
如果列表中没有破损的包裹或特殊的轮子,它可以顺利运行...
你可以试试这个:
for i in ` pip list | awk -F ' ' '{print $1}'`; do pip install --upgrade $i; done
相当神奇的蛋黄使这很容易。
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
它可以做很多你可能会觉得有用的事情。
采用:
pip install -r <(pip freeze) --upgrade
拉马纳的回答对我来说是最好的,在这里,但我不得不添加一些问题:
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 中删除的包。
致 endolith:我也希望有一个 easy pip.install(dist.key, upgrade=True)
,但它看起来不像 pip 打算被命令行使用(文档没有提到内部 API,pip 开发人员也没有使用文档字符串)。
通过拉取请求发送给 pip 人;同时使用我写的这个 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
这似乎对我有用......
pip install -U $(pip list --outdated | awk '{printf $1" "}')
之后我使用printf
了一个空格来正确分隔包名。
Windows 上最短和最简单的。
pip freeze > requirements.txt && pip install --upgrade -r requirements.txt && rm requirements.txt
这应该更有效:
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>=3)print}'
跳过标题行cut -d' ' -f1
获取第一列xargs -n1 pip install -U
从它左侧的管道中获取 1 个参数,并将其传递给命令以升级包列表。这是 Python 3 的 PowerShell 解决方案:
pip3 list --outdated --format=legacy | ForEach { pip3 install -U $_.split(" ")[0] }
对于 Python 2:
pip2 list --outdated --format=legacy | ForEach { pip2 install -U $_.split(" ")[0] }
这将一一升级软件包。所以一个
pip3 check
pip2 check
之后应该确保没有依赖关系被破坏。
JSON + jq答案:
pip list -o --format json | jq '.[] | .name' | xargs pip install -U
virtualenv
这是通过 pip更新所有 Python 3 包(在激活的)中的代码:
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)
这是我对rbp 答案的变体,它绕过了“可编辑”和开发分布。它与原始版本有两个相同的缺陷:重新下载和重新安装不必要的;并且一个包上的错误将阻止之后每个包的升级。
pip freeze |sed -ne 's/==.*//p' |xargs pip install -U --
相关的错误报告,从 Bitbucket 迁移后有点脱节:
这是一个仅更新过时软件包的脚本。
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)
采用:
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。
查看所有过时的软件包
pip list --outdated --format=columns
安装
sudo pip install pipdate
然后输入
sudo -H pipdate
下面的 Windowscmd
代码片段执行以下操作:
- 升级
pip
到最新版本。- 升级所有过时的软件包。
- 对于每个正在升级的包,检查
requirements.txt
任何版本说明符。
@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
我已经尝试了 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)
这是在 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])
我最近一直在使用pur。这很简单,也很重要。它会更新您的requirements.txt
文件以反映升级,然后您可以requirements.txt
像往常一样使用您的文件进行升级。
$ 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 ...
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 友好。
正如这里的另一个答案所说:
pip freeze --local | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 pip install -U
是一个可能的解决方案:这里的一些评论(包括我自己)在使用此命令时存在权限问题。对以下内容进行一些更改为我解决了这些问题。
pip freeze --local | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 sudo -H pip install -U
请注意添加sudo -H
的允许命令以 root 权限运行的内容。
cmd中的一行:
for /F "delims= " %i in ('pip list --outdated --format=legacy') do pip install -U %i
所以一个
pip check
之后应该确保没有依赖关系被破坏。
我能找到的最短和最简单的:
pip install -U $(pip freeze | cut -d"=" -f1)
该$(cmd)
键允许您包装任何 shell 命令行(它返回其输出)。
在 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
要升级默认 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'))
没有必要这么麻烦或安装一些包。
在Linux shell上更新 pip 包:
pip list --outdated --format=freeze | awk -F"==" '{print $1}' | xargs -i pip install -U {}
在Windows powershell上更新 pip 包:
pip list --outdated --format=freeze | ForEach { pip install -U $_.split("==")[0] }
几点:
pip
为您的 python 版本pip3
或pip2
.pip list --outdated
检查过时的 pip 包。--format
在我的 pip 版本 22.0.3 上只有 3 种类型:列(默认)、冻结或 json。freeze
在命令管道中是更好的选择。python -c 'import pip; [pip.main(["install", "--upgrade", d.project_name]) for d in pip.get_installed_distributions()]'
一个班轮!
如果您只想升级由 pip 安装的软件包,并避免升级由其他工具(如 apt、yum 等)安装的软件包,那么您可以使用我在我的 Ubuntu 上使用的这个脚本(可能也适用于其他发行版) - 基于这篇文章:
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
pip list --outdated --format=freeze | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 pip install -U