setup.py (已弃用)

在引入基于 pyproject.toml 的构建(在 PEP 517PEP 518 中)之前,pip 仅支持使用 setup.py 文件安装包,这些文件使用 setuptools 构建。

这里记录的接口目前仅出于遗留目的保留,直到迁移到基于 pyproject.toml 的构建完成。

注意

pip 对各种 setup.py 调用方式的参数和语法被认为是与 setuptools 强耦合的实现细节。此构建系统接口不应被任何其他构建后端使用,这些后端应该基于 pyproject.toml 构建系统接口。

此外,项目不应期望围绕 setup.py 接口存在任何形式的向后兼容性保证。

构建过程

构建包的整体过程是

  • 生成包的元数据。

  • 为包生成一个 wheel。

如果需要,wheel 随后可用于执行安装。

元数据生成

作为第一步,pip 需要获取关于包的元数据(名称、版本、依赖项等)。它通过调用 setup.py egg_info 来收集这些信息。

egg_info 命令会生成包的元数据,pip 随后可以消费这些元数据并继续收集包的所有依赖项。一旦依赖项解析过程完成,pip 将继续执行这些包的构建过程的下一阶段。

Wheel 生成

当提供一个包的 源代码发行版(或“sdist”) 时,pip 将尝试构建一个 wheel。由于 wheel 发行版可以被 缓存,这可以大大加快包的未来安装速度。

这是通过调用 setup.py bdist_wheel 来完成的,这需要安装 wheel 包。

如果 wheel 生成成功(这可能包括编译 C/C++ 代码,具体取决于包),生成的 wheel 将被添加到 pip 的 wheel 缓存中,并将用于本次安装。构建的 wheel 由 pip 在本地缓存,以避免重复的相同构建。

如果 wheel 生成失败,pip 会运行 setup.py clean 来清理可能已生成的任何构建工件。之后,pip 将尝试直接安装。

可编辑安装

对于以“可编辑”模式安装包 (pip install --editable),pip 将调用 setup.py develop,它将使用 setuptools 的机制来执行可编辑/开发安装。

Setuptools 注入

为了支持直接使用 distutils 的项目,pip 在调用 setup.py 之前将 setuptools 注入 sys.modules。这种注入对于基于 distutils 的项目来说应该是透明的。

定制构建

--global-option--build-option 参数用于 pip installpip wheel 会将额外的参数注入到 setup.py 命令中 (--build-option 仅在 pip wheel 中可用)。

注意

使用 --global-option--build-option 非常依赖于 setuptools,并且被认为更多是当前实现中的一个意外,而不是一个受支持的接口。它在这里记录是为了完整性。一旦这个构建系统接口被删除,这些标志将不再受支持。

这些参数在命令中包含如下:

python setup.py <global_options> BUILD COMMAND <build_options>

选项会直接传递,目前提供了对 distutils 命令行的直接访问。例如

$ python -m pip wheel --global-option bdist_ext --global-option -DFOO wheel
$ python -m pip wheel --global-option bdist_ext --global-option -DFOO wheel
C:> py -m pip wheel --global-option bdist_ext --global-option -DFOO wheel

将导致 pip 调用

setup.py bdist_ext -DFOO bdist_wheel -d TARGET

这会将一个预处理器符号传递给扩展构建。

构建输出

构建系统产生的任何输出都会被 pip 读取(如果请求则显示给用户)。为了正确读取构建系统输出,pip 要求输出以明确定义的编码方式写入,具体来说是用户为文本输出配置的编码方式(可以通过 Python 中的 locale.getpreferredencoding 获取)。如果配置的编码方式是 ASCII,pip 假设为 UTF-8(以考虑某些 Unix 系统的行为)。

构建系统应确保其调用的任何工具(编译器等)以正确的编码方式生成输出。在实践中,尤其是在 Windows 上,工具在使用“OEM”和“ANSI”代码页方面不一致,这可能并非总是可行。因此,如果遇到编码错误的构建工具输出,pip 会尝试通过将意外的字节序列转换为 Python 风格的十六进制转义序列 ("\x80\xff" 等) 来干净地恢复。但是,输出仍然有可能使用错误的编码方式显示(乱码)。