是否可以使用pip一次性升级所有Python包?
注意:官方问题跟踪器上对此有一个功能请求。
是否可以使用pip一次性升级所有Python包?
注意:官方问题跟踪器上对此有一个功能请求。
当前回答
拉玛纳回答的一个线性版本。
python -c 'import pip, subprocess; [subprocess.call("pip install -U " + d.project_name, shell=1) for d in pip.get_installed_distributions()]'
其他回答
下面是用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])
这是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
之后应该确保没有中断依赖关系。
更稳健的解决方案
对于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命令行特性的变化而导致的可移植性问题由于常见的pip或pip3子进程故障导致xargs崩溃来自原始xargs输出的拥挤日志记录依赖Python到OS桥,同时可能升级它3
上面的命令使用最简单和最可移植的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组件可能会导致死锁或包数据库损坏。
以下Windows cmd代码段执行以下操作:
将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
您可以只打印过期的软件包:
pip freeze | cut -d = -f 1 | xargs -n 1 pip search | grep -B2 'LATEST:'