PyPI上传必需字段为name、version、description、readme;name须小写且仅含字母数字和短横线,version须符合PEP 440,description不能为空,readme须指定路径如"README.md"。

pyproject.toml 里哪些字段是 PyPI 上传必需的
不填 name、version、description、authors 这四个字段,twine upload 会成功,但 PyPI 页面会显示不全甚至拒绝索引——尤其是 name 和 version 缺一不可,否则 build 阶段就报错:Invalid sdist: filename does not match PEP 508 name。
实操建议:
-
name必须小写、用短横线(-)分隔,不能含下划线或大写字母;PyPI 不接受my_package或MyPackage,只认my-package -
version推荐用dynamic = true+setuptools-scm自动推导,避免手动改多个地方;若静态写死,必须符合 PEP 440(如"0.1.0",不能写"v0.1.0"或"0.1") -
authors是数组,每个元素是{name = "...", email = "..."};只写字符串(如authors = "Alice")会被 setuptools 忽略 -
readme字段要明确指定路径和格式,例如readme = "README.md",否则build会警告并降级为纯文本
classifier 怎么选才不影响用户安装
错误填写 classifiers 不会阻止上传,但会导致包在 PyPI 搜索中不可见、被误判为“仅限 Python 2”或“开发版”,甚至触发依赖解析器跳过该版本。
常见问题:
立即学习“Python免费学习笔记(深入)”;
- 漏掉
"Programming Language :: Python :: 3"→ PyPI 认为这是 Python 2 包,现代 pip 默认不安装 - 写了
"Development Status :: 3 - Alpha"却没加requires-python = ">=3.8"→ 用户用 Python 3.7 安装时不会报错,但运行时报ModuleNotFoundError - 把
"License :: OSI Approved :: MIT License"写成"MIT License"→ PyPI 不识别,许可证栏显示为空
实操建议:用 PyPI 官方分类器列表 复制粘贴,不要手敲;核心必选包括:Programming Language :: Python :: 3、对应的具体版本(如 :: 3.9)、License :: OSI Approved :: ...、Operating System :: OS Independent(除非你真依赖 Windows API)。
动态 version 和静态 version 哪种更适合 CI 发布
CI 环境下用静态 version = "0.2.0" 最简单,但极易出错:git tag、pyproject.toml、CHANGELOG 三处不同步,就会导致发布版本号混乱或重复。
推荐用动态方案,但要注意工具链兼容性:
-
setuptools-scm是目前最稳的选择,只要 git repo 有 tag(如v0.2.0),它就能自动算出0.2.0或0.2.0.dev1+gabc123;需在[build-system]中声明requires = ["setuptools>=45", "wheel", "setuptools-scm[toml]>=6.2"] - 别用
__version__文件 +dynamic.version.file:某些构建后端(如buildCLI)可能读不到,且 CI 中容易因缓存导致版本号滞后 - CI 脚本里执行
python -m build前,确保git fetch --tags已运行,否则setuptools-scm算不出正确版本
为什么 build 后的 sdist 里没有 LICENSE 文件
不是 pyproject.toml 没配对,而是默认打包逻辑只包含 py 文件和 readme,其他文件(LICENSE、py.typed、examples/)必须显式声明。
解决方式只有两个有效路径:
- 用
[project.files](PEP 621,新标准):写files = [{include = "LICENSE"}],但注意目前pip install从 sdist 安装时仍可能忽略它 - 更可靠的是用
[tool.setuptools.manifest]+MANIFEST.in:在项目根目录建MANIFEST.in,写include LICENSE;同时确保[build-system]的requires包含setuptools(而非仅setuptools-core) - 验证方法:运行
python -m build --sdist后解压生成的.tar.gz,检查顶层是否含LICENSE;缺了就说明 manifest 没生效
最容易被忽略的是:即使 pyproject.toml 里写了 license = {text = "MIT"},也不会自动把 LICENSE 文件打进包——这个字段只用于 PyPI 页面展示,和实际分发无关。


















