如何在构建时不引入运行时依赖,实现pyproject.toml包动态版本化?
最优解决方案:轻量动态版本化方案(规避重型构建依赖)
方案1:使用setuptools-scm轻量模式
- 直接借助
setuptools-scm工具实现Git版本追踪,无需自行编写哈希逻辑 - 仅需在
pyproject.toml中添加基础配置,不会将主包的GPU依赖拉入构建环节:[build-system] requires = ["setuptools>=61.0", "setuptools-scm"] build-backend = "setuptools.build_meta" [tool.setuptools-scm] root = "." version_scheme = "post-release" local_scheme = "dirty-tag" - 优势:无需额外虚拟包,构建时仅读取Git信息,适配无GPU的笔记本环境;版本格式如
0.1.0+gabc123(abc123为Git哈希前缀),可直接写入训练日志
方案2:自定义轻量版本生成脚本(完全可控)
若不想依赖第三方工具,可编写极简脚本隔离主包依赖:
- 在项目根目录创建
get_version.py,仅实现Git哈希读取:import subprocess import os def get_git_hash(): try: result = subprocess.run( ["git", "rev-parse", "--short", "HEAD"], capture_output=True, text=True, check=True, cwd=os.path.dirname(os.path.abspath(__file__)) ) return result.stdout.strip() except: return "unknown" __version__ = f"0.1.0+{get_git_hash()}" - 在
pyproject.toml中配置动态版本指向该脚本属性:[build-system] requires = ["setuptools>=61.0"] build-backend = "setuptools.build_meta" [tool.setuptools.dynamic] version = {attr = "get_version.__version__"} - 配置文件包含规则,确保构建时能读取脚本,但不将其作为包内容安装:
[tool.setuptools.package-data] "" = ["get_version.py"]
- 优势:版本格式完全自定义,无额外依赖,构建仅运行轻量脚本,不会触发主包GPU依赖安装
方案3:预生成版本文件(适配CI/CD或离线场景)
若在CI环境构建,或本地可提前生成版本文件:
- 编写
generate_version.py,运行后在主包目录生成_version.py:import subprocess def main(): try: hash = subprocess.check_output(["git", "rev-parse", "--short", "HEAD"]).strip().decode() with open("my_main_package/_version.py", "w") as f: f.write(f'__version__ = "0.1.0+{hash}"\n') except: with open("my_main_package/_version.py", "w") as f: f.write('__version__ = "0.1.0+unknown"\n') if __name__ == "__main__": main() - 在主包
__init__.py中导入版本:from ._version import __version__ - 在
pyproject.toml中配置动态读取主包版本:[tool.setuptools.dynamic] version = {attr = "my_main_package.__version__"}
- 优势:构建过程无Git依赖,适合离线或无Git环境;用户仅安装主包,无额外冗余文件
原临时方案的问题
虚拟包方案会导致用户安装两个包,既不规范又易混淆,且完全没必要——上述方案均能在不引入额外包的前提下实现Git哈希版本追踪,同时避免将GPU依赖拉入构建环境。
内容的提问来源于stack exchange,提问作者Jatentaki
相关产品推荐
相关产品推荐

