Python 打包的未来:pyproject.toml 全方位指南

大家好!在我们的系列文章中,我们已经深入探讨了 setup.pyconda-build 这两种强大的打包工具。您可能已经注意到,社区正在逐步从使用 setup.py 这个可执行的 Python 脚本,转向一个名为 pyproject.toml 的静态配置文件。

这不仅仅是一个简单的文件格式变化,它代表了 Python 打包理念的一次重要演进。为什么需要这个新文件?它又该如何使用呢?

本文将为您全面解析 pyproject.toml,这个被 PEP 518 和 PEP 621 等提案确立为官方标准的现代化打包工具。

一、 开发者篇:使用 pyproject.toml 定义你的项目

作为项目的创建者,拥抱 pyproject.toml 能让你的项目配置更清晰、更标准,并能将以往散落在各种文件(setup.py, setup.cfg, MANIFEST.in 等)中的配置统一起来。

1. 为什么要使用 pyproject.toml
  • 标准化:它是官方指定的、统一的 Python 项目配置文件格式。
  • 声明式,非可执行:与 setup.py 不同,toml 文件是静态的,只声明“是什么”,而不是执行“做什么”。这使得构建过程更安全、更可预测。
  • 统一配置入口:它不仅能定义项目元数据和依赖,还能统一存放 black, pytest, ruff, mypy 等开发工具的配置,让项目根目录更整洁。
  • 构建系统解耦:它允许你自由选择构建后端(如 setuptools, poetry, pdm, hatch),而不仅仅是绑定 setuptools
2. 如何创建 pyproject.toml

pyproject.toml 是一个基于 TOML (Tom’s Obvious, Minimal Language) 语法的文本文件,您需要在项目根目录手动创建它。

项目结构示例:

my_modern_project/ ├── my_awesome_tool/ │ ├── __init__.py │ └── main.py ├── tests/ │ └── test_main.py └── pyproject.toml <-- 我们要创建的文件 

pyproject.toml 文件详解:

一个遵循 PEP 621 标准的现代化 pyproject.toml 核心内容如下:

# pyproject.toml # 1. 构建系统声明 (必需) # 告诉 pip 等工具,这个项目需要用什么来构建 (这里是 setuptools) [build-system] requires = ["setuptools>=61.0"] build-backend = "setuptools.build_meta" # 2. 项目核心元数据 (必需) # 这部分取代了 setup.py 中的大部分参数 [project] name = "my-awesome-tool" version = "0.1.0" authors = [ { name="你的名字", email="你的邮箱@example.com" }, ] description = "一个功能强大的现代工具" readme = "README.md" # 指定 README 文件 requires-python = ">=3.9" license = { text = "MIT" } classifiers = [ "Programming Language :: Python :: 3", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", ] # 3. 依赖项 (核心) # 这取代了 setup.py 中的 install_requires dependencies = [ "requests>=2.20", "numpy", "click", ] # 4. 命令行工具 (可选) # 这取代了 setup.py 中的 entry_points [project.scripts] awesome_tool = "my_awesome_tool.main:cli" # 5. 可选依赖 (可选) # 允许用户安装额外功能,例如 pip install "my-awesome-tool[extra]" [project.optional-dependencies] extra = ["pandas"] # 6. 项目链接 (可选) [project.urls] Homepage = "https://github.com/your_username/my_modern_project" "Bug Tracker" = "https://github.com/your_username/my_modern_project/issues" 

可以看到,它的结构清晰、可读性强,并且几乎涵盖了 setup.py 的所有核心功能。

3. 开发和安装

开发流程与 setup.py 完全相同。您依然需要在一个虚拟环境中进行开发,并使用 pip 以可编辑模式安装:

# 在激活虚拟环境后,于项目根目录运行 pip install -e .

pip (较新版本) 会自动识别 pyproject.toml 文件,并根据其中的配置来正确安装项目及其依赖。

二、 用户篇:如何使用 pyproject.toml 定义的项目

作为用户,你可能根本感觉不到任何区别,这正是 pyproject.toml 标准化的美妙之处。

1. 安装流程

当你从 GitHub 下载了一个包含 pyproject.toml 的项目后,安装步骤和传统项目一模一样

  1. 创建并激活虚拟环境 (依然是最佳实践)。
  2. 安装项目
    • 作为普通用户使用:pip install .
    • 作为贡献者开发:pip install -e .

pip 会在后台自动处理所有事情。它会读取 pyproject.toml,理解项目的构建需求和依赖,然后下载并安装所有需要的东西。用户无需关心底层是用 setuptools 还是 poetry 构建的。

三、 总结与优势

pyproject.toml 是 Python 打包的未来,它的优势非常明显:

特性setup.py (传统方式)pyproject.toml (现代方式)
文件格式Python 脚本,可执行TOML 配置文件,声明式
标准性事实标准,但配置分散官方标准 (PEP 518/621)
配置配置分散在 setup.py, setup.cfg 等多个文件中集中管理,可包含项目元数据、依赖和各种开发工具的配置
安全性执行任意代码有潜在风险静态文件,更安全,构建过程更可预测
灵活性强绑定 setuptools可自由选择构建后端 (setuptools, poetry, pdm, hatch 等)

四、 那如果项目文件里既有setup.py又有pyproject.toml呢?


pyproject.toml 是现代 Python 打包流程的唯一入口,它的优先级更高。

当一个构建工具(例如 pip)开始工作时,它会首先寻找 pyproject.toml。这个文件决定了接下来该做什么,以及由谁(哪个构建后端)来做。

下面我们来详细分解一下具体的读取和处理逻辑。


读取流程:三步走

  1. 入口 (pyproject.toml[build-system] 部分)
    • pip 首先打开 pyproject.toml,并且只读取 [build-system] 这个表格。
    • 这个表格告诉 pip:“嘿,要构建这个项目,你需要使用 setuptools(或者 poetry, pdm 等)这个工具。”
    • pip 会确保这个构建工具被安装,然后把控制权完全交给它。
  2. 构建后端接管 (例如 setuptools)
    • 现在,setuptools (作为构建后端) 开始工作。它的任务是收集项目的所有元数据(包名、版本、依赖等)。
    • setuptools 会再次查看 pyproject.toml 文件,寻找一个名为 [project] 的表格。
  3. 元数据读取的优先级
    • 这就是决定性的步骤,会根据文件内容分为以下几种情况:

两种主要场景

场景一:现代项目 (最佳实践)
  • 文件状态:
    • pyproject.toml:包含了完整的 [project] 表格,里面定义了 name, version, dependencies 等所有核心信息。
  • 读取方式:
    • setuptools优先读取 pyproject.toml 中的 [project] 表格作为所有元数据的“唯一真实来源”。
    • 它会忽略setup.py 文件中的任何元数据(如果有的话)。
    • 那个简单的 setup.py 文件仅仅是为了兼容一些非常老旧的、不认识 pyproject.toml 的工具。

setup.py要么不存在,要么是一个非常简单的“垫片”文件,内容可能只有:

# setup.py (shim)from setuptools import setup setup()

结论:在这种模式下,pyproject.toml 完胜。

场景二:过渡期项目 (非常普遍)
  • 文件状态:
    • pyproject.toml:只包含了 [build-system] 表格,可能还有一些工具配置(如 [tool.pytest]),但没有 [project] 表格
    • setup.py:包含一个完整的 setup() 函数,里面定义了 name, version, install_requires 等所有信息。
  • 读取方式:
    • pip 仍然从 pyproject.toml 开始,得知需要使用 setuptools
    • setuptools 接管后,在 pyproject.toml找不到 [project] 表格
    • 于是,setuptools回退 (fallback) 到它的传统模式:去执行 setup.py 文件,并从 setup() 函数的参数中提取所有的项目元数据。

结论:在这种模式下,pyproject.toml 扮演“指路人”的角色,而 setup.py 仍然是“信息提供者”。


总结与建议

场景pyproject.toml 内容setup.py 内容读取优先级 / 谁说了算?
现代包含 [build-system][project]不存在或仅为简单垫片pyproject.toml 说了算。元数据从 [project] 表格读取。
过渡仅包含 [build-system]包含完整的 setup() 函数setup.py 说了算pyproject.toml 仅用于指定构建工具。
冲突 (应避免)[project]setup() 都定义了元数据[project]setup() 都定义了元数据pyproject.toml 说了算setuptools 会优先采用 [project] 表格中的值。

如果 pyproject.toml 文件中包含了完整的 [project] 表格(定义了项目名称、版本、依赖等),同时又存在一个完备的 setup.py 文件,那么现代化的构建工具(如新版 pipsetuptools)会:默认优先使用 pyproject.toml 文件中的信息。

pyproject.toml 是官方指定的“新版蓝图”,而 setup.py 是“旧版蓝图”。当两种蓝图都在时,构建系统会默认遵循更新、更标准的那一份。旧的 setup.py 文件中的配置在很大程度上会被忽略,以避免冲突和混淆。

Read more

【OpenClaw从入门到精通】第10篇:OpenClaw生产环境部署全攻略:性能优化+安全加固+监控运维(2026实测版)

【OpenClaw从入门到精通】第10篇:OpenClaw生产环境部署全攻略:性能优化+安全加固+监控运维(2026实测版)

摘要:本文聚焦OpenClaw从测试环境走向生产环境的核心痛点,围绕“性能优化、安全加固、监控运维”三大维度展开实操讲解。先明确生产环境硬件/系统选型标准,再通过硬件层资源管控、模型调度策略、缓存优化等手段提升响应速度(实测响应效率提升50%+);接着从网络、权限、数据三层构建安全防护体系,集成火山引擎安全方案拦截高危操作;最后落地TenacitOS可视化监控与Prometheus告警体系,配套完整故障排查清单和虚拟实战案例。全文所有配置、代码均经实测验证,兼顾新手入门实操性和进阶读者的生产级部署需求,帮助开发者真正实现OpenClaw从“能用”到“放心用”的跨越。 优质专栏欢迎订阅! 【DeepSeek深度应用】【Python高阶开发:AI自动化与数据工程实战】【YOLOv11工业级实战】 【机器视觉:C# + HALCON】【大模型微调实战:平民级微调技术全解】 【人工智能之深度学习】【AI 赋能:Python 人工智能应用实战】【数字孪生与仿真技术实战指南】 【AI工程化落地与YOLOv8/v9实战】【C#工业上位机高级应用:高并发通信+性能优化】 【Java生产级避坑指南:

By Ne0inhk
ARM Linux 驱动开发篇--- Linux 并发与竞争实验(互斥体实现 LED 设备互斥访问)--- Ubuntu20.04互斥体实验

ARM Linux 驱动开发篇--- Linux 并发与竞争实验(互斥体实现 LED 设备互斥访问)--- Ubuntu20.04互斥体实验

🎬 渡水无言:个人主页渡水无言 ❄专栏传送门: 《linux专栏》《嵌入式linux驱动开发》《linux系统移植专栏》 ❄专栏传送门: 《freertos专栏》《STM32 HAL库专栏》 ⭐️流水不争先,争的是滔滔不绝  📚博主简介:第二十届中国研究生电子设计竞赛全国二等奖 |国家奖学金 | 省级三好学生 | 省级优秀毕业生获得者 | ZEEKLOG新星杯TOP18 | 半导纵横专栏博主 | 211在读研究生 在这里主要分享自己学习的linux嵌入式领域知识;有分享错误或者不足的地方欢迎大佬指导,也欢迎各位大佬互相三连 目录 前言  一、实验基础说明 1.1、互斥体简介 1.2 本次实验设计思路 二、硬件原理分析(看过之前博客的可以忽略) 三、实验程序编写 3.1 互斥体 LED 驱动代码(mutex.c) 3.2.1、设备结构体定义(28-39

By Ne0inhk
Flutter for OpenHarmony:swagger_dart_code_generator 接口代码自动化生成的救星(OpenAPI/Swagger) 深度解析与鸿蒙适配指南

Flutter for OpenHarmony:swagger_dart_code_generator 接口代码自动化生成的救星(OpenAPI/Swagger) 深度解析与鸿蒙适配指南

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net 前言 后端工程师扔给你一个 Swagger (OpenAPI) 文档地址,你会怎么做? 1. 对着文档,手写 Dart Model 类(容易写错字段类型)。 2. 手写 Retrofit/Dio 的 API 接口定义(容易拼错 URL)。 3. 当后端修改了字段名,你对着报错修半天。 这是重复劳动的地狱。 swagger_dart_code_generator 可以将 Swagger (JSON/YAML) 文件直接转换为高质量的 Dart 代码,包括: * Model 类:支持 json_serializable,带 fromJson/

By Ne0inhk
Linux 开发别再卡壳!makefile/git/gdb 全流程实操 + 作业解析,新手看完直接用----《Hello Linux!》(5)

Linux 开发别再卡壳!makefile/git/gdb 全流程实操 + 作业解析,新手看完直接用----《Hello Linux!》(5)

文章目录 * 前言 * make/makefile * 文件的三个时间 * Linux第一个小程序-进度条 * 回车和换行 * 缓冲区 * 程序的代码展示 * git指令 * 关于gitee * Linux调试器-gdb使用 * 作业部分 前言 做 Linux 开发时,你是不是也遇到过这些 “卡脖子” 时刻?写 makefile 时,明明语法没错却报错,最后发现是依赖方法行没加 Tab;想提交代码到 gitee,记不清 git add/commit/push 的 “三板斧”,还得反复搜教程;用 gdb 调试程序,输了命令没反应,才想起编译时没加-g生成 debug 版本;甚至连写个进度条,都搞不懂\r和\n的区别,导致进度条乱跳…… 其实这些问题,

By Ne0inhk