setuptools-scm生成带.devXXX版本无法上传PyPi,求根因
setuptools-scm 生成带.devXXX后缀版本号导致无法上传PyPI的问题解析
问题背景
我维护的几个代码仓库里,setuptools-scm开始生成带.devXXX后缀的版本号,这种版本标签无法上传到PyPI。一开始以为是Git操作不当导致的,就通过use_scm_version自定义版本逻辑做了临时修复,但现在就连新建的简单项目也出现了同样的问题,想搞清楚根本原因。
根本原因
setuptools-scm生成.dev后缀版本号的核心原因是当前代码目录处于非干净的Git标签状态,常见触发场景包括:
- 代码在已打正式Git标签(比如
v1.0.0)之后又有新的提交 - 本地工作区存在未提交的修改(包括新增、修改文件,或未暂存的变更)
- 在GitHub Action等CI环境中,默认的代码拉取操作没有获取完整的Git标签信息,或者拉取的是某个具体提交而非正式标签
- 本地的Git标签未推送到远程仓库,或本地与远程标签不一致
setuptools-scm的默认逻辑是:当检测到当前代码处于「正式标签之后的开发阶段」时,会自动添加.devXXX后缀(XXX为提交次数或提交哈希值),用来标记这是一个未发布的开发版本。而PyPI的正式仓库不接受带有.dev后缀的开发版本,因此导致上传失败。
临时解决代码
以下是通过自定义use_scm_version逻辑去除.dev后缀的临时修复代码:
# setup.py def _clean_version(): """ 解决scm在GitHub Action上生成开发版本号的问题 """ def get_version(version): return str(version.tag) def empty(version): return '' return {'local_scheme': get_version, 'version_scheme': empty} setuptools.setup( ... use_scm_version=_clean_version, ... )
彻底解决建议
如果想从根源上避免这个问题,发布版本时需要确保:
- 本地工作区完全干净,没有未提交的修改(可通过
git status确认) - 切换到要发布的正式Git标签上(执行
git checkout <标签名>) - 在CI环境中,配置代码拉取步骤获取完整的Git历史和标签(比如GitHub Actions中使用
actions/checkout@v4并设置fetch-depth: 0) - 确认本地标签已推送到远程仓库(执行
git push origin --tags)
内容的提问来源于stack exchange,提问作者Nick Gimbal
相关产品推荐
相关产品推荐

