pip install 仅读取 [build-system] 和 [project] 两个顶层表;前者需指定 requires 构建依赖,后者必填 name 和 version,其他字段如 [tool.*] 或 optional-dependencies 不影响安装行为。

pyproject.toml 里哪些字段是 pip install 时真正读的
pip install(包括从源码构建)只认 [build-system] 和 [project] 这两个顶层表。其他字段比如 [tool.black] 或 [project.optional-dependencies] 不影响安装行为,只是工具约定。
常见错误:把 requires-python 写在 [tool.poetry] 下,结果 pip 完全无视——它只看 [project].requires-python。
-
[build-system.requires]必须包含构建依赖,例如["setuptools>=45", "wheel"];缺了可能导致ModuleNotFoundError: No module named 'setuptools.build_meta' -
[project]中name、version是必填项,否则 pip 构建失败并报错Invalid pyproject.toml config: 'project.name' is required -
[project.version]推荐用动态方式(如dynamic = ["version"]+[tool.setuptools.dynamic.version]),硬编码易遗漏发布前更新
setuptools、flit、poetry 对 [project] 字段的支持差异
不是所有字段在所有构建后端里都生效。比如 [project.urls] 在 setuptools 和 flit 中生成 wheel 的 METADATA 正确,但 poetry 2.0+ 默认忽略它,除非显式启用 include = ["pyproject.toml"]。
使用场景:你想让 pip show mypkg 显示项目主页和文档链接,就得确认当前构建后端是否导出 [project.urls] 到元数据。
立即学习“Python免费学习笔记(深入)”;
-
[project.dependencies]所有后端都支持,但格式必须是 PEP 508 字符串列表,不能写成嵌套 TOML 表 -
[project.optional-dependencies]全支持,但注意 poetry 会把 key 名自动转为小写并去空格,"django Support"变成django-support -
[project.entry-points."console_scripts"]setuptools/flit 没问题;poetry 需要额外配置[tool.poetry.plugins."console_scripts"]才能注册
动态 version 怎么写才不被 pip build 忽略
直接写 version = "1.2.3" 看似简单,但版本号一变就要手动改,CI/CD 容易出错。动态方案得让构建后端“看得见、算得对”。
最容易踩的坑:用 Python 文件读取 __version__.py,但没在 [build-system] 中声明该文件为构建依赖,导致在干净环境中构建失败。
- 推荐做法:用
[project.version]设为dynamic = ["version"],再配[tool.setuptools.dynamic.version]+attr = "mymodule.__version__" - 路径必须可 import:如果模块不在
src/下,得同步设[tool.setuptools.package-dir],否则构建时报ModuleNotFoundError - 避免用
file方式读取版本文件——TOML 解析器不执行 Python,file = "VERSION"仅在 setuptools 61.0+ 支持,且要求文件纯文本不含任何逻辑
windows 上 pyproject.toml 路径或换行符引发的构建失败
不是语法问题,而是环境细节:CRLF 换行、bom 头、路径含中文或空格,都会让某些构建后端(尤其是旧版 setuptools)静默失败或报奇怪错误。
典型现象:pip wheel . 卡住几秒后退出,无报错;或提示 Invalid value for 'project.name': must be non-empty,其实 name 明明写了。
- 保存为 UTF-8 无 BOM(Notepad++ / VS Code 都可设),BOM 会导致 TOML 解析器跳过首行
- 避免在
[project.readme]中写相对路径如readme = "README.md",如果项目根目录路径含空格,部分后端解析失败;改用readme = {file = "README.md"}更稳 - Windows 用户若用 git bash,确保
core.autocrlf设为true,否则 CRLF 可能被误判为非法字符
事情说清了就结束。字段再多,最终起作用的也就那几个表;工具再花哨,pip 只信 [project] 和 [build-system]。其他全是锦上添花,别当真。