Python包的构建是一些不同的工具在标准化过程中协调的产物。作为一个包的作者,你最大的选择之一是使用哪一套工具。评估每个工具的细微差别是很困难的,尤其是当你是打包新手的时候。幸运的是,各种工具正在围绕相同的核心工作流程进行标准化,所以一旦你学会了它,你就能以最小的努力在各种工具之间进行切换。
这篇文章涵盖了你首先需要学习的关于Python构建系统本身的部分。
要跟上这篇文章,你需要安装和使用 build。如果你以前没有做过,请看下面的步骤。
安装 build
build(github.com/pypa/build) 是 Python Packaging Authority (PyPA) 提供的一个工具,用于构建 Python 包。
使用下面的命令安装 build:
python -m pip install build
为了验证你的配置,运行下面的命令:
$ python -m build—version
在你的软件包的根目录下,先用下面的命令运行build :
$ python -m build-build
因为你的包还没有内容,你应该看到一个类似下面的错误:
ERROR Source /Users/<you>/code/first-python-package does not appear to be
<linearrow /> a Python project: no pyproject.toml or setup.py
输出中提出了两个文件建议。pyproject.toml 是 PEP 518(https://www.python.org/dev/peps/pep-0518/) 中引入的用于配置 Python 打包的较新的标准文件,除非你想使用的第三方工具只与setup.py 兼容,否则应该优先使用。该文件使用 TOML(https://toml.io/en/),一种类似 INI 的语言,将配置分成相关部分。使用以下命令创建pyproject.toml 文件,以纠正错误。
$ touch pyproject.toml
再次运行build 命令。这一次,构建应该成功运行,你应该看到大量的输出,其中有几行值得注意,如列表1所示。这里发生了什么?在高层次上,构建命令消耗你的源代码和你提供的元数据,以及它生成的一些文件,以创建。
- 一个源代码发布包:一个 Python 源码发布包,或称
sdist,是一个源代码的压缩存档文件,扩展名为.tgz。 - 一个二进制发布包:一个 Python 内置发行包是一个二进制文件。目前内置发行包的标准是所谓的轮子或
bdist_wheel,一个扩展名为.whl的文件。
清单 1.构建一个空的 Python 软件包的结果:
...
Successfully installed setuptools-57.0.0 wheel-0.36.2
❶ Setuptools 和 wheel 包被用于构建后端
❷ 源分发包是由 build_sdist 钩子 构建的
❸ 构建过程希望得到一个 README 文件,该文件有几种格式可供选择
❷ 构建过程希望得到软件包的名称和 URL
❺ 构建过程希望有一个软件包的作者或维护者
❻ 由于没有指定名称,软件包被称为 UNKNOWN
❼ 源码分布是一个压缩的档案文件
二进制轮子发行包是由 build_wheel 钩子 构建的。
❾ 二进制轮子发行包是一个 .whl 文件
因为你还没有提供任何元数据,所以构建过程会提醒你缺少一些重要的信息,比如README 文件、作者等等。添加这些信息将在本章后面介绍。
请注意,构建过程会安装setuptools 和wheel 包。Setuptools(https://setuptools.readthedocs.io) 是一个库,在很长一段时间里,它是创建 Python 包的唯一方法之一。现在,Setuptools 是用于 Python 软件包构建的多种可用的构建后端之一。
定义:一个构建后端是一个Python对象,它提供了几个必要的和可选的钩子来实现打包行为。核心的构建后端接口在 PEP 517(https://www.python.org/dev/peps/pep-0517/#build-backend-interface) 中定义。
一个构建后端在构建过程中完成了创建软件包工件的后勤工作,即通过build_sdist 和build_wheel 钩子。Setuptools在build_wheel 步骤中使用wheel 包来构建轮子。当你没有指定后端时,build 工具默认使用Setuptools作为构建后端。
构建后台的存在可能会让你怀疑是否也会有构建前台。事实证明,你已经在使用一个构建前台了。build 工具就是一个构建前台。
定义: 构建前台是一个你运行的工具,用来启动从源代码构建软件包。构建前端提供一个用户界面,并通过钩子接口与构建后端集成。
简而言之,你使用一个构建前台工具,比如build 来触发一个构建后台,比如 Setuptools 来从你的源代码和元数据中创建软件包工件(图1)。
图 1.Python 构建系统由一个前端用户界面组成,它与后端集成以构建软件包工件。
因为构建过程会创建软件包工件,所以现在可以检查运行构建的效果。现在列出你的包的根目录的内容。你应该看到以下内容:
$ ls -a1 $HOME/code/first-python-package/
.
..
.venv/
UNKNOWN.egg-info/
build/
dist/
pyproject.toml
UKNOWN.egg-info/ 和build/ 目录是中间的工件。列出dist/ 目录的内容,你应该看到源代码和二进制轮子包文件:
$ ls -a1 $HOME/code/first-python-package/dist/
UNKNOWN-0.0.0-py3-none-any.whl
UNKNOWN-0.0.0.tar.gz
其他构建系统工具
正如我前面提到的,对于构建前台和后台都存在其他的选择。有些软件包同时提供前台和后台,但我喜欢build 和Setuptools。
如果你想探索一些其他的构建工具,可以看看poetry(https://python-poetry.org/)和flit(https://flit.readthedocs.io)。每个构建系统都在配置的简易性、能力和用户界面之间做了不同的权衡。例如,flit和poetry是针对纯Python软件包的,而Setuptools可以支持其他语言的扩展。
你可以通过几个步骤切换到另一个构建系统:
- 安装新的构建前台包
- 更新
pyproject.toml,以指定新的构建后端和它的要求 - 将软件包的元数据转移到新的构建后端所期望的位置
记得build ,因为你没有指定,所以使用Setuptools作为后备构建后端。你可以通过在pyproject.toml 中添加列表2中的行来指定Setuptools作为你的软件包的构建后端。 这些行指定了以下内容。
build-system- 本节描述了软件包的构建系统。requires- 这些是依赖关系的列表,以字符串的形式,必须安装这些依赖关系才能使构建系统工作。一个Setuptools构建系统需要setuptools和wheel,正如你在本章前面看到的那样。build-backend- 这确定了构建后端对象的入口,使用点状路径作为字符串。Setuptools的构建后台对象可以在setuptools.build_meta。
这些代表了你需要指定构建后端的完整配置。
清单 2.一个使用Setuptools的构建系统后端规范
[build-system]
❶ 打开一个新的 TOML 部分
❷ 以字符串形式列出软件包的名称
以字符串形式列出对象的带点路径 ❷以字符串形式列出对象的带点路径
一旦你添加了构建系统的信息,再次运行构建。输出结果应该没有变化:你只是把 Setuptools 锁定为显式后端,而不是让build 把它作为默认的。现在你已经掌握了 Python 软件包构建系统,你需要添加一些关于你的软件包的元数据。你可以在这本书中读到所有的内容。