首页 文章

如何从运行时代码访问PyInstaller钩子文件命名空间中的变量?

提问于
浏览
1

我试图在PyInstaller分析阶段获得 git describe 的输出,并使其可用于Python运行时变量,以便为应用程序提供从构建环境派生并在运行时显示的修订字符串 .

为此,我假设PyInstaller钩子是最好的方法,因为它们允许在构建导入树时在钩子文件中执行任意Python代码 . 但是,我还没有找到一种方法将PyInstaller分析阶段的变量值传递给运行时变量,以便它可以由作为生成的 .exe 文件运行的应用程序显示 .

示例:钩子文件 hook-rev.py ,当遇到 import rev 时由PyInstaller分析机制导入:

import git

rev = git.Repo().git.describe()
print('got rev = {}'.format(rev))

mymodule.py 包含:

import rev

rev.py 包含:

global AppRev
try:
    # Get the revision from the hook file
    AppRev = rev
except:
    print('rev is not defined')

运行PyInstaller:

pyinstaller --additional-hooks-dir=. mymodule.py

确认在PyInstaller分析阶段触发了钩子文件导入,并且当PyInstaller构建导入树时,print语句显示 git describe 的正确结果被分配给钩子文件范围内的变量 rev . 但生成的 .exe 文件会产生:

rev is not defined

当然,鉴于代码示例,这是正确的,因为 rev 不在本地或其他可访问的命名空间中 . 我不知道钩子文件的命名空间是什么,因此 rev 变量是什么 .

通过添加此print语句

print('module name = {}'.format(__name__))

在钩子文件中 hook-rev.py 我看到PyInstaller的钩子导入机制将名称 __PyInstaller_hooks_0_rev 分配给导入的钩子模块 . 但是此导入仅在构建期间存在,因此尝试在 run.py 中在运行时访问 rev 变量为 __PyInstaller_hooks_0_rev.rev 失败,因为模块 __PyInstaller_hooks_0_rev 在运行时未知 .

是否有另一种方法可以在运行时和PyInstaller钩子导入处理之间桥接命名空间?

1 回答

  • 0

    作为参考,这是一种实现所需功能的方法 . 它不是一个理想的解决方案,因为它依赖于另外两个Python文件(钩子文件,PyInstaller和运行时之间共享的生成文件)来实现我希望只用钩子文件可能实现的目标 . 它还有一个缺点,即在开发环境中显示的应用程序修订版本反映了PyInstaller最后设置的修订版本 . 我不会将此标记为已接受的答案,除非很明显更简单的方法是不可能的 .

    大纲是:

    • 在应用程序中,使用 import rev 触发PyInstaller钩子机制,在分析阶段查找要导入的文件 hook-rev.py

    • hook-rev.py 中构造修订字符串并写出一个Python文件,例如 buildrev.py 包含对变量的修订字符串赋值

    • rev.py 中使用 import buildrev 并定义 get_rev() ,返回 buildrev.rev

    • 在应用程序文件中,通过调用 rev.get_rev() 访问修订字符串

    实现此方案的文件如下所示 .

    mymodule.py (主要应用):

    import rev
    
    print('application revision is', rev.get_rev())
    

    rev.py (定义 get_rev() ,返回修订字符串):

    # import buildrev fails in dev environment if PyInstaller has not been run
    try:
        import buildrev
        rev_string = buildrev.rev
    except:
        rev_string = 'unknown'
    
    def get_rev():
        return rev_string
    

    hook-rev.py (PyInstaller在分析阶段导入的钩子文件生成 buildrev.py ):

    try:
        # Get the build-time revision string and write it into
        # buildrev.py as a Python variable assignment. Must search
        # parent directories because PyInstaller analyze is run in a lower level.
        rev_string = git.Repo(search_parent_directories=True).git.describe()
        with open('buildrev.py', 'w') as rev_file:
            print('rev = \'{}\''.format(rev_string), file=rev_file)
    except: 
        pass
    

    在生成的文件 buildrev.py 中,修订字符串反映了PyInstaller导入树构建时的工作副本修订 . 当使用普通的Python解释器访问时,如在开发环境中的IDE中,该修订字符串仍然反映最后一次运行PyInstaller时工作空间的版本,这可能是不准确的 . VCS不应跟踪 buildrev.py .

相关问题