注意
此部分文档目前正在编写中。pip 开发人员欢迎您帮助完成此文档。如果您有兴趣帮忙,请在 跟踪问题 中告诉我们。
概述功能¶
pip 是一个包安装器。
pip 不仅仅是安装工具,它还有缓存、配置和命令行界面,这些界面本身也有一些特性。但主要来说
pip 所做的事情
- 管理包的构建 (将包构建卸载到后端),当需要时 (源代码分发包 - 如果包是 wheel,则不需要此操作)。
- 默认情况下,出于向后兼容性原因,pip 将包构建委托给 setuptools。但 setuptools 的问题在于:它有一个
setup.py
文件,它会调用该文件以 …… 获取信息?
决定将东西安装在哪里。一旦包构建完成,生成的工件就会被安装到系统中,放置在适当的位置。 PEP 517 定义了构建后端和安装器之间的接口。
流程概述¶
按照顺序,pip 做了什么?
获取用户输入 (用户提供的字符串,说明他们想要安装哪个包)
弄清楚这意味着什么:用户准确请求了什么 - 将其转换为 pip 可以操作的东西 (用户输入到需求)
整个过程的核心?一旦从步骤 2 获取了一组需求,您必须将其扩展为具体的“要安装的东西” - 根据用户给出的需求,弄清楚要安装哪些其他需求,以及从哪里获取它们。
- 此步骤很复杂 - 也是探索性的,涉及依赖关系
解析 - 我们需要访问索引,查看哪些版本可用
- 有时您需要构建包本身才能获取
依赖关系信息,这意味着从包索引中获取包,这意味着需要知道它是否存在。对于单个包,
安装要安装的实际项目。
为什么?pip 从 PyPI 以外的地方安装!但同样,我们以前从未对 PyPI 的 JSON API 进行过保证,因此没有人从 PyPI 获取元数据,而与下载包本身分开。
从安装过程的流程角度来看
对于 1 个包:获取该包的抽象需求,并尝试查看这意味着什么 (此抽象需求可以采用多种形式)。定义抽象依赖关系。
一旦我们有一组“此包,从这里获取,这是该包的该版本”,
修改环境以安装这些东西 (这意味着:将文件放在正确的位置)。例如:如果您已经拥有版本 6.0 的需求,而您正在安装 7.2,则卸载 6.0 并安装 7.2。
下载过程¶
安装中会发生什么?嗯,install
的一个子集,pip 通常在 pip install
期间执行的操作是 download
(也作为 pip download 命令提供给用户)。我们下载并检查包以获取清单。对于任何给定的包名称,我们需要知道哪些文件可用以及它们的文件名是什么。
pip 可以从 Python 包库中下载,包在库中以结构化格式存储,这样像 pip 这样的安装器就可以找到它们。
PEP 503 定义了我们与 Python 包库通信时使用的 API。
PyPI¶
如果我们运行 pip download somepackage
而不带其他参数会发生什么?默认情况下,我们查看 PyPI,这是 pip 知道在哪里寻找更多信息的地方,以了解包索引关于 somepackage
的信息。
pip
然后知道:哪些文件可用,以及它们的文件名是什么。
换句话说
在所有依赖关系都未解决之前,请执行以下操作
按照 PEP 503 中定义的 API,从 http://{pypi_index}/simple/{package_name}
解析页面中的所有文件链接。
从链接列表中选择一个要下载的文件。
从下载的包中提取元数据。
根据元数据更新依赖关系树。
包索引通过 (现有的 PyPI API) 为 pip 提供了该包的文件列表。这些文件包含版本和其他一些信息,可以帮助 pip 决定是否应该下载这些文件。
pip 从列表中选择一个文件下载。
它可能会返回并选择另一个文件下载。
当 pip 查看包索引时,它查看的地方基本上有一个链接。链接的文本是文件名。
这是 PyPI Simple API (PyPI 拥有多个 API,一些 API 正在被弃用)。pip 查看 Simple API,最初在 PEP 503 中进行了记录 - packaging.python.org 拥有 PyPA 规范,其中包含有关 Simple Repository API 的更多详细信息。
对于这个包名称 - 这是可用文件的列表。
在那里寻找
文件名列表
其他信息
一旦有了这些,它就会选择一个文件并下载。
(问题:如果我想要 pip install flask
,我认为整个文件名列表不能……不应该……?我只要 Flask……为什么我会得到整个列表?
答案:它不是每个文件,只是 Flask 的文件。没有 API 用于获取 PyPI 上的所有文件。它是用于获取所有 Flask 文件的。)