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

时间:2018-12-09 02:44:23

标签: python git hook pyinstaller

我试图在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构建过程中,打印语句显示git describe的正确结果已分配给挂钩文件范围内的变量rev导入树。但是生成的.exe文件会产生:

rev is not defined

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

通过添加此打印声明

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

在钩子文件hook-rev.py中,我看到PyInstaller的钩子导入机制为导入的钩子模块分配了名称__PyInstaller_hooks_0_rev。但是此导入仅在构建期间存在,因此由于在运行时未知模块rev,因此尝试在run.py中以__PyInstaller_hooks_0_rev.rev的身份在__PyInstaller_hooks_0_rev中访问function checkForChanges() { var contentDate = null; var frequency = 5000; setInterval(() => { let xmlhttp = new XMLHttpRequest(); xmlhttp.addEventListener("load", (progressEvent) => { console.log("Content loaded()"); if (contentDate==null) { contentDate = xmlhttp.response.lastModified; return; } if(xmlhttp.response.lastModified != contentDate) { window.location.reload(true); } }); //xmlhttp.open("GET", window.location.href); xmlhttp.open("HEAD", window.location.href); //xmlhttp.responseType = "blob"; xmlhttp.send(); }, frequency); } checkForChanges(); 变量失败。 / p>

还有另一种方法可以在运行时和PyInstaller挂钩导入处理之间架起名称空间吗?

1 个答案:

答案 0 :(得分:0)

作为参考,这是一种实现所需功能的方法。这不是理想的解决方案,因为它依赖于两个附加的Python文件(挂钩文件,在PyInstaller和运行时之间共享的生成文件)来实现我希望仅通过挂钩文件就能实现的目标。缺点还在于,开发环境中显示的应用修订反映了PyInstaller最后设置的修订。除非明确指出不可能使用更简单的方法,否则我不会将其标记为可接受的答案。

大纲是:

  1. 在应用程序中,使用import rev触发PyInstaller挂钩机制,以寻找要在分析阶段导入的文件hook-rev.py
  2. hook-rev.py中构造修订字符串并写出Python文件,例如buildrev.py包含修订字符串到变量的分配
  3. rev.py中使用import buildrev并定义返回get_rev()的{​​{1}}
  4. 在应用程序文件中,通过调用buildrev.rev
  5. 来访问修订字符串。

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

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 (由PyInstaller在分析阶段导入的钩子文件生成hook-rev.py

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 中,修订字符串反映了PyInstaller导入树构建时的工作副本修订。 当使用普通的Python解释器访问时(例如在开发环境中的IDE中),该修订字符串仍反映了PyInstaller上次运行时工作区的版本,这可能是不准确的。 VCS不应跟踪buildrev.py