历史背景
PEP 517 和 PEP 518 是 pyproject.toml 诞生的关键推动力:
- PEP 518 (2016) :提出了
pyproject.toml
文件格式,用于指定构建系统要求 - PEP 517 (2017):定义了构建前端和后端的接口标准,使构建过程标准化
- 传统问题:之前依赖 setup.py 和 setuptools,缺乏标准化,构建环境不一致
设计原理
- 声明式配置:使用 TOML 格式,更易于机器解析和人类阅读
- 构建系统隔离:明确指定构建依赖,避免环境污染
- 可扩展性:支持多种构建后端(setuptools, poetry, flit, hatch等)
- 元数据统一:包含项目元数据、构建配置、工具配置等
setup.py vs pyproject.toml 调用方法差异
setup.py(传统方式)
python
# setup.py
from setuptools import setup, find_packages
setup(
name="my-package",
version="1.0.0",
packages=find_packages(),
install_requires=[
"requests>=2.25.0",
"numpy>=1.19.0"
],
extras_require={
"dev": ["pytest", "black"],
"docs": ["sphinx"]
},
entry_points={
"console_scripts": [
"my-cli=my_package.cli:main"
]
}
)
构建命令:
bash
# 源码安装
python setup.py install
# 开发模式
python setup.py develop
# 构建分发包
python setup.py sdist bdist_wheel
pyproject.toml(现代方式)
toml
# pyproject.toml
[build-system]
requires = ["setuptools>=61.0.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "my-package"
version = "1.0.0"
dependencies = [
"requests>=2.25.0",
"numpy>=1.19.0"
]
[project.optional-dependencies]
dev = ["pytest", "black"]
docs = ["sphinx"]
[project.scripts]
my-cli = "my_package.cli:main"
[tool.setuptools]
packages = {find = {}}
构建命令:
bash
# 使用 PEP 517 兼容工具构建
pip install -e . # 开发模式
pip install . # 安装
python -m build # 构建分发包
# 或者使用特定后端
python -m setuptools.build_meta
关键差异对比
特性 | setup.py | pyproject.toml |
---|---|---|
格式 | Python 代码 | TOML 声明式配置 |
构建依赖 | 隐式依赖 setuptools | 显式声明在 [build-system] |
环境隔离 | 差,依赖全局环境 | 好,明确构建环境 |
可重现性 | 低 | 高 |
安全性 | 执行任意代码 | 只读配置 |
元数据 | 代码中定义 | 声明式配置 |
扩展性 | 有限 | 支持多种后端 |
RPM 包管理版本支持情况
RPM 版本支持时间线
RPM 版本 | 发布时间 | pyproject.toml 支持 | 关键特性 |
---|---|---|---|
RPM 4.11 | 2015 | ❌ 不支持 | 传统 setup.py only |
RPM 4.12 | 2017 | ⚠️ 有限支持 | 初步 PEP 517 实验 |
RPM 4.13 | 2018 | ⚠️ 基本支持 | 支持 %pyproject_buildrequires |
RPM 4.14 | 2019 | ✅ 基本完整 | 支持 %pyproject_wheel |
RPM 4.15 | 2020 | ✅ 完整支持 | 完整 PEP 517/518 支持 |
RPM 4.16+ | 2021+ | ✅ 成熟支持 | 优化构建流程 |
不同 RPM 版本的 spec 文件写法
RPM 4.11-4.12(传统方式)
spec
%build
python setup.py build
%install
python setup.py install --root=%{buildroot}
RPM 4.13-4.14(过渡期)
spec
%build
# 手动处理 pyproject.toml
python -m pip wheel --no-deps --no-build-isolation -w dist .
%install
python -m pip install --no-deps --no-index --find-links=dist \
--prefix=%{buildroot}%{_prefix} .
RPM 4.15+(现代方式)
spec
%build
%pyproject_wheel
%install
%pyproject_install
针对低版本 RPM 4.14 的解决方案
spec
# 对于 RPM 4.14,需要手动实现 PEP 517 构建
%build
export PIP_NO_BUILD_ISOLATION=0
export PYTHONPATH=%{_builddir}/%{name}-%{version}
# 手动构建 wheel
python -m pip wheel --no-deps --no-build-isolation --wheel-dir=dist .
%install
rm -rf %{buildroot}
mkdir -p %{buildroot}%{python3_sitearch}
# 手动安装 wheel
WHEEL_FILE=$(ls dist/*.whl | head -1)
python -m pip install --no-index --no-deps --ignore-installed \
--target=%{buildroot}%{python3_sitearch} \
--no-build-isolation \
${WHEEL_FILE}
构建后端支持矩阵
构建后端 | RPM 4.14 支持 | RPM 4.15+ 支持 | 说明 |
---|---|---|---|
setuptools | ✅ 通过 pip wheel | ✅ 原生支持 | 最常用 |
poetry | ⚠️ 需要 poetry-core | ✅ 完整支持 | 需要额外依赖 |
flit | ⚠️ 需要手动处理 | ✅ 完整支持 | 简单项目 |
hatch | ⚠️ 有限支持 | ✅ 完整支持 | 新兴工具 |
pdm | ❌ 不支持 | ⚠️ 有限支持 | 较新工具 |
兼容性建议
- 对于低版本 RPM :使用
pip wheel
手动构建 - 检查构建后端:确保构建依赖在 RPM 环境中可用
- 测试验证:在不同 RPM 版本上测试构建过程
- 回退方案:准备 setup.py 作为备选(如果需要支持很旧的系统)
现状总结
- RPM 4.15+ :推荐使用
%pyproject_wheel
和%pyproject_install
- RPM 4.14:需要手动处理,但可以正常工作
- RPM 4.13 及以下:建议升级或使用传统 setup.py 方式
现在大多数现代 Linux 发行版(RHEL 8+、Fedora、openEuler 等)都使用 RPM 4.14+,可以较好地支持 pyproject.toml 构建。