在 Python Pip 基础教程 - 日常使用 章节中我们讲解了日常使用的一些 pip
命令,但我回去翻了下 pip
的官方文档,发现 pip install
命令的用法远远不止这些,本章节,我们就来深入探讨下 pip install
命令的一些高级用法
安装本地包
在某些情况下,我们可能只能从本地代码中安装软件包,而不访问 PyPI
一般情况下,对于本地的软件包,我们都会将其解压,然后进入到该软件的 setup.py
文件所在目录下,打开 cmd,并切换到该目录下,先执行 python setup.py build
构建软件包,然后使用 python setup.py install
安装,当然了,有时候我们可以直接使用 python setup.py install
而省去构建的环节
对于一个软件包,这种安装方式是不错的,但如果有多个软件包呢,如果只给定了一个 requirements.txt
文件的情况,我们又要如何安装呢?
很多时候,比如作为运维工程师,大部分的服务器都不能够访问外网,也禁止外网访问它们。但是,外网可以通过一台跳板机来访问这些机器
如果要在这些机器上安装 requirements.txt
文件中的第三方包,又要怎么做呢?
这时候,我们就要祭出 pip install
这个神器了,它还有一些额外的用法
- 首先,使用下面的命令将
requirements.txt
中所有的软件包及其依赖都下载到本地的一个目录$ pip install --download DIR -r requirements.txt
DIR
表示为软件包要存放的目录
需要注意的是,pip install --download
在尝试从 PyPI
官方仓库中下载包之前会首先查看本机的 wheel
缓存
对于某个软件包,如果我们之前从未安装过它,那么在本地是不存在它的缓存的。在这种情况下,如果我们的 requirements.txt
中的软件包还不存在 wheel
,但我们有想要一个 wheel
,就可以使用下面的命令来创建一个 wheel
$ pip wheel --wheel-dir DIR -r requirements.txt
-
然后我们就可以将
DIR
目录及其包含所有wheel
文件复制到另一台机器,然后再指定的目录DIR
中使用下面的命令来安装$ pip install --no-index --find-links=DIR -r requirements.txt
这条命令中,我们使用到了
--no-index
参数,用户表示不从远程访问,而参数--find-links
表示素有需要安装的软件包,都从DIR
这个目录中查找
需要注意的是,这三个命令中的 requirements.txt
内容必须一模一样,以防止出现一些意想不到的情况
「 仅在需要时 」递归升级
pip install --upgrade
命令,也就是 pip install -U
命令,有一个 --upgrade-strategy
命令行选项用于控制 pip 如何处理依赖项的升级。
它支持两种升级依赖项的策略
-
急切 (
eager
) : 升级所有依赖项,无论它们是否满足新的父级的软件包的要求 -
仅在需要时 (
only-if-needed
) : 仅在不满足新的父级的软件包时才升级依赖关系
默认的策略是 only-if-needed
,但从 pip 10.0
版本开始,改成了 eager
,主要的原因还是为了解决升级时依赖项的冲突问题
作为一个历史性的注解,早期的 only-if-needed
策略修复该问题的解决方案是
pip install --upgrade --no-deps SomePackage pip install SomePackage
当然了,反对默认使用 eager
的人则提出了 upgrade-all
命令,被认为是对急切升级行为的更安全的替代方案
用户安装
一种称之为 「 用户方案 」安装 的概念随着 Python 2.6
的发布而进入大众的视野
这套方案意味者所有的 Python 发行版都支持特定于用户的备用安装位置,每个操作系统的默认位置都在 Python 文档的 site.USER_BASE 变量的中进行了解释
对于 Pip 来说,可以通过在 pip install
命名中添加 --user
选项来打开此安装模式
此外,可以通过设置 PYTHONUSERBASE
环境变量来定制 「 用户方案 」,该变量会更新 site.USER_BASE
的值
要将 SomePackage
安装到将 site.USER_BASE
环境指定的 /myappenv
目录中,可以执行以下命令
export PYTHONUSERBASE=/myappenv pip install --user SomePackage
pip install --user
遵循以下四条规则:
-
当需要安装的软件包已经安装在全局的 python 路径上,并且已经存在的版本与需要安装的版本发生冲突时,全局的版本会被忽略,且不会被卸载
-
当需要安装的软件包已经安装在全局的 python 路径上,并且满足需要安装的版本,pip 不执行任何操作,而是直接报告满足要求,这种情况类似于类似于在虚拟环境 ( virtualenv ) 中使用
--system-site-packages
参数安装软件包时,全局软件包如何满足要求的时候 -
pip install --user
在--no-site-packages
的虚拟环境 ( virtualenv ) 中是无效的,结果等同于pip install
,由于用户站点不在 python 路径上。安装没有意义 -
在
--no-site-packages
的虚拟环境 ( virtualenv ) 中,如果要安装的包已经存在于site-packages
下,且与想要安装的包的版本发生冲突,pip 并不会安装该版本的软件包,因为在sys.path
变量中,--user
安装的优先级明显低于virtualenv
,所以安装也变得毫无意义
为了方便你清晰的了解这四条规则,我们下面将结合一些范例来讲解
在 --no-site-packages
的虚拟环境 ( virtualenv ) 中 ( 即默认类型 ) 中安装某个软件包
$ pip install --user SomePackage
Can not perform a '--user' install. User site-packages are not visible in this virtualenv.
在 --system-site-packages
的虚拟环境 ( virtualenv ) 中,假设已经存在 SomePackage==0.3
的软件包,则
$ pip install --user SomePackage==0.4 Will not install to the user site because it will lack sys.path precedence
在一个真正的 Python 中,假设全局未安装 SomePackage
$ pip install --user SomePackage [...] Successfully installed SomePackage
在一个真正的 Python 中,假设全局已经安装 SomePackage
,但不是最新的版本,则提示
$ pip install --user SomePackage [...] Requirement already satisfied (use --upgrade to upgrade) $ pip install --user --upgrade SomePackage [...] Successfully installed SomePackage
在一个真正的 Python 中,假设全局已经安装 SomePackage
,且已经是最新的版本,则提示
$ pip install --user SomePackage [...] Requirement already satisfied (use --upgrade to upgrade) $ pip install --user --upgrade SomePackage [...] Requirement already up-to-date: SomePackage # force the install $ pip install --user --ignore-installed SomePackage [...] Successfully installed SomePackage
结束语
是不是很有趣,一个小小的 pip install
尽然有这么多知识,真的是打开眼界