在冻结的 Python 脚本 (Cx_Freeze) 中显示 git 提交哈希

Display git commit hash in frozen Python script (Cx_Freeze)

我有一个 python 项目并使用 git 作为版本控制软件。 该软件将使用 Cx_Freeze.

进行部署

我想在我的应用程序的“关于”对话框中显示在构建过程(冻结脚本)期间捕获的版本和作者(可能还有其他元数据)。

这是设置脚本的示例:

import sys
import subprocess

from cx_Freeze import setup, Executable

build_exe_options = {}
base = "Win32GUI"
version = subprocess.run(['git', 'describe', '--abbrev=4', '--dirty', '--always', '--tags'],
                         capture_output=True, encoding='utf-8').stdout.strip()

setup(
    name="XY",
    version=version,
    author="My Name",
    description="Mysterious GUI application",
    options={"build_exe": build_exe_options},
    executables=[Executable("XY.py", base=base)],
)

关于对话框的简单示例:

from tkinter import messagebox

def on_about():
    messagebox.showinfo(f'About', 'Software XY, written by {author}, version {version}')
    # Should display e.g. 'Software XY, written by My Name, version 4b06-dirty'

有谁知道这是否可行以及如何实现? 在此先感谢大家!

我想到了第一个解决方案,在执行安装脚本时,我在应用程序的主包中创建了一个 sub-module。只有当 __version__ 变量被冻结并且 sub-module 存在时,我才将 __version__ 变量导入到该包的 __init__.py 中:

setup.py:

import subprocess
import os.path

import mymodule

from cx_Freeze import setup, Executable


def create_versionmodule(packagepath: str):
    """
    creates a file packagepath/_version.py which defines a __version__ variable
    which contains the stripped output of "git describe --dirty --always --tags"
    """
    
    version = subprocess.run(['git', 'describe', '--dirty', '--always', '--tags'],
                             capture_output=True, encoding='utf-8').stdout.strip()
    with open(os.path.join(packagepath, '_version.py'), mode='w', encoding='utf-8') as file:
        file.write(f'__version__: str = {version!r}\n')


build_exe_options = {}
base = "Win32GUI"

create_versionmodule(packagepath=os.path.dirname(mymodule.__file__))

setup(
    name="XY",
    description="Mysterious GUI application",
    options={"build_exe": build_exe_options},
    executables=[Executable("XY.py", base=base)],
)

mymodule/__init__.py:

import sys as _sys

__version__ = 'UNKNOWN'
if getattr(_sys, "frozen", False):
    try:
        from mymodule._version import __version__
    except ModuleNotFoundError:
        pass

现在我可以从代码中的任何位置访问版本变量:

import mymodule

from tkinter import messagebox

def on_about():
    messagebox.showinfo(f'About', 'Software XY, version {mymodule.__version__}')