setuptools_scm能从git标签生成版本号,但要求项目根目录有.git且已打符合语义化规范的tag(如v1.2.3),否则fallback为dev格式;需在pyproject.toml中正确配置build-system和project.dynamic=["version"],并确保ci获取完整git历史。

直接用 setuptools_scm 就能从 Git 标签生成版本号,但前提是你的项目根目录有 .git,且已打过符合语义化规范的 tag(如 v1.2.3)。否则它会 fallback 到“未发布”格式(如 0.1.0.dev1+gabc1234),不是你想要的稳定版号。
确保 Git 仓库状态满足 setuptools_scm 要求
setuptools_scm 不读 setup.py 或 pyproject.toml 以外的任何元数据,它只依赖 Git 历史。常见失败原因不是配置错,而是仓库本身不达标:
- 项目目录必须是 Git 工作区根目录(即运行
git rev-parse --show-toplevel应返回当前路径) - 最近一次 commit 必须有 tag,且 tag 名要匹配默认正则
^v?(\d+\.\d+\.\d+)$(比如v1.2.3或1.2.3都行,release-1.2.3就不行) - 如果没 tag,它会按距离最近 tag 的提交数 + 当前 commit hash 构造 dev 版本,这不是 bug,是设计行为
在 pyproject.toml 中启用 setuptools_scm
现代 Python 项目应使用 pyproject.toml,而不是旧式 setup.py。关键配置只有两处,别多写:
[build-system] requires = ["setuptools>=45", "setuptools_scm[toml]>=6.2"] build-backend = "setuptools.build_meta" <p>[project] name = "mylib"</p><h1>不要写 version 字段!交给 setuptools_scm 动态生成</h1><p>dynamic = ["version"]</p><p>[project.optional-dependencies] dev = ["setuptools_scm"]</p><p>[tool.setuptools_scm]</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill6081" title="python-code-analyz"><img src="https://img.php.cn/upload/skill/000/000/081/179077148379011.jpg" alt="python-code-analyz" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/skill6081" title="python-code-analyz" class="overflowclass">python-code-analyz</a> <p class="overflowclass">专业Python代码分析与优化,支持语法检查、安全扫描、性能评估、复杂度分析及重构后优化代码生成。</p> </div> <a rel="nofollow" href="/xiazai/skill6081" title="python-code-analyz" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div><h1>可选:放宽 tag 匹配规则(例如支持 'v1.2.3-beta.1')</h1><h1>version_scheme = "guess-next-dev"</h1><h1>local_scheme = "node-and-date"</h1>
注意:dynamic = ["version"] 是必需的,否则 setuptools 会忽略 setuptools_scm 的注入;requires 里必须显式包含 setuptools_scm[toml],否则 toml 解析器可能缺失。
验证版本号是否真被正确读取
别靠 pip install -e . 后 import 看 __version__ —— 这个值可能来自源码里硬编码的 fallback,而非 Git。真正可靠的验证方式是:
- 运行
python -m setuptools_scm:它会直接输出当前解析出的版本字符串,且附带调试信息(如 “tag ‘v1.2.3’ found” 或 “no tag found”) - 构建 sdist/wheel 后解压,检查生成的
PKG-INFO或mylib-*.dist-info/METADATA里的Version:字段 - 在干净虚拟环境中
pip install ./dist/mylib-*.tar.gz,再import mylib; print(mylib.__version__)
如果 python -m setuptools_scm 输出的是 0.0.0,说明它根本没找到 Git 信息——大概率是当前路径不在 Git 仓库内,或 .git 被误删/忽略。
最常被忽略的一点:CI 环境中 clone 的仓库默认是 shallow(--depth=1),没有完整历史和 tag。必须显式加 git fetch --tags --prune 或设置 fetch-depth: 0(GitHub Actions)才能让 setuptools_scm 正常工作。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










