You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于uv构建的Python项目:如何在uv run及虚拟环境运行时自动获取带脏标记的Git哈希版本

基于uv构建的Python项目:如何在uv run及虚拟环境运行时自动获取带脏标记的Git哈希版本

我来分享几个适合你场景的实用方案,都是开发者们常用的实践,应该能解决你觉得步骤繁琐的问题:

方案1:运行时直接计算Git版本(零构建依赖,开发阶段首选)

这个方法完全跳过预生成版本文件的步骤,直接在代码里实时获取Git哈希和脏标记,最适合你日常用uv run的开发场景。

核心思路是:在应用入口代码里,调用Git命令或通过Git库读取仓库状态,不用任何构建钩子或额外步骤。

代码示例

在mypkg/myapp.py里加入版本获取逻辑:

import subprocess
from pathlib import Path

def get_git_version():
    # 定位项目根目录(假设当前文件在src/mypkg下,根目录往上两级)
    repo_root = Path(__file__).parent.parent.parent
    try:
        # 获取短Git哈希
        hash_result = subprocess.run(
            ["git", "rev-parse", "--short", "HEAD"],
            capture_output=True,
            text=True,
            cwd=repo_root,
            check=True
        )
        git_hash = hash_result.stdout.strip()

        # 检查是否有未提交的修改(脏标记)
        status_result = subprocess.run(
            ["git", "status", "--porcelain"],
            capture_output=True,
            text=True,
            cwd=repo_root,
            check=True
        )
        if status_result.stdout.strip():
            git_hash += "-dirty"

        return git_hash
    except (subprocess.CalledProcessError, FileNotFoundError):
        # 处理Git不可用或不在仓库的情况
        return "unknown (Git not accessible)"

def main():
    version = get_git_version()
    print(f"Usage: myapp ...")
    print(f"Version: {version}")
    # 你的应用业务逻辑...

优点

  • 完全不需要构建步骤,uv run myapp直接就能显示最新版本;如果用uv pip install -e .做可编辑安装,虚拟环境里直接运行myapp也能实时更新版本。
  • 不用依赖任何第三方工具或构建钩子,代码简洁直观。

注意

如果是非可编辑模式安装(比如uv pip install .),安装后的代码在site-packages目录下,不在Git仓库范围内,这个方法就拿不到版本了。所以它更适合开发阶段,发布版本可以搭配下面的方案2。

方案2:用Versioningit + Hatch 覆盖全场景(开发+发布)

你之前试过Versioningit,它其实完全能解决你的问题,可能是没配置好可编辑模式的支持。它会在构建时生成固定版本,在可编辑安装时动态计算版本,完美覆盖uv run和uv pip install两种场景。

配置步骤

  1. 安装开发依赖:
uv add --dev versioningit hatchling
  1. 修改pyproject.toml:
[project]
dynamic = ["version"]  # 让版本由versioningit动态生成

[tool.versioningit]
vcs = "git"
style = "short"        # 使用短Git哈希
dirty-mark = "+dirty"  # 脏状态的标记后缀
# 自动生成版本文件,供应用代码读取
write = {file = "src/mypkg/_version.py", template = "version = '{version}'"}

[build-system]
requires = ["hatchling", "versioningit"]
build-backend = "hatchling.build"

[tool.hatch.build.hooks.versioningit]
enable = true  # 启用Hatch的Versioningit构建钩子
  1. 在应用代码里读取版本:
try:
    # 优先从生成的版本文件读取
    from mypkg._version import version
except ImportError:
    #  fallback到运行时计算(比如开发初期还没构建的情况)
    from mypkg.myapp import get_git_version
    version = get_git_version()

def main():
    print(f"Version: {version}")

效果

  • 开发时:执行uv pip install -e .做一次可编辑安装,之后无论是uv run myapp还是虚拟环境里直接运行myapp,都会自动显示最新的Git哈希+脏标记。
  • 发布时:执行uv build或uv pip install .,Versioningit会在构建时生成固定的版本号(包含当时的Git状态),打包到安装包中,运行时直接读取固定版本。

这个方案是最专业的,完全不用手动干预版本,覆盖所有使用场景。

方案3:自定义UV脚本别名(简化手动步骤)

如果你不想引入新工具,只是觉得之前的两步操作太繁琐,可以把生成版本文件和运行/安装的步骤封装成UV的自定义脚本,一键执行。

在pyproject.toml里添加:

[tool.uv.scripts]
# 一键运行应用(自动先更新版本文件)
run = "python write_version_to_file.py && uv run myapp"
# 一键安装应用(自动先更新版本文件)
install = "python write_version_to_file.py && uv pip install --force-reinstall ."

之后你只需要执行:

# 一键运行应用
uv run run
# 一键安装应用
uv run install

就自动完成了版本文件生成+运行/安装的两步操作,不用手动敲两个命令,也不用记复杂参数。

总结

  • 如果你主要是开发阶段用,优先选方案1,零依赖最省心。
  • 如果需要兼顾开发和发布场景,选方案2,自动化程度最高且专业。
  • 如果你不想改代码或加依赖,选方案3,用别名简化操作流程。

备注:内容来源于stack exchange,提问作者Bioman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.13 17:58:02