pyproject.toml 的历史背景和原理

发布于:2025-09-12 ⋅ 阅读:(18) ⋅ 点赞:(0)

历史背景

PEP 517 和 PEP 518 是 pyproject.toml 诞生的关键推动力:

  1. PEP 518 (2016):提出了 pyproject.toml 文件格式,用于指定构建系统要求
  2. PEP 517 (2017):定义了构建前端和后端的接口标准,使构建过程标准化
  3. 传统问题:之前依赖 setup.py 和 setuptools,缺乏标准化,构建环境不一致

设计原理

  1. 声明式配置:使用 TOML 格式,更易于机器解析和人类阅读
  2. 构建系统隔离:明确指定构建依赖,避免环境污染
  3. 可扩展性:支持多种构建后端(setuptools, poetry, flit, hatch等)
  4. 元数据统一:包含项目元数据、构建配置、工具配置等

setup.py vs pyproject.toml 调用方法差异

setup.py(传统方式)

# 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"
        ]
    }
)

构建命令

# 源码安装
python setup.py install

# 开发模式
python setup.py develop

# 构建分发包
python setup.py sdist bdist_wheel

pyproject.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 = {}}

构建命令

# 使用 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(传统方式)
%build
python setup.py build

%install
python setup.py install --root=%{buildroot}
RPM 4.13-4.14(过渡期)
%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+(现代方式)
%build
%pyproject_wheel

%install
%pyproject_install

针对低版本 RPM 4.14 的解决方案

# 对于 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 ❌ 不支持 ⚠️ 有限支持 较新工具

兼容性建议

  1. 对于低版本 RPM:使用 pip wheel 手动构建
  2. 检查构建后端:确保构建依赖在 RPM 环境中可用
  3. 测试验证:在不同 RPM 版本上测试构建过程
  4. 回退方案:准备 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 构建。