我试图在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挂钩导入处理之间架起名称空间吗?
答案 0 :(得分:0)
作为参考,这是一种实现所需功能的方法。这不是理想的解决方案,因为它依赖于两个附加的Python文件(挂钩文件,在PyInstaller和运行时之间共享的生成文件)来实现我希望仅通过挂钩文件就能实现的目标。缺点还在于,开发环境中显示的应用修订反映了PyInstaller最后设置的修订。除非明确指出不可能使用更简单的方法,否则我不会将其标记为可接受的答案。
大纲是:
import rev
触发PyInstaller挂钩机制,以寻找要在分析阶段导入的文件hook-rev.py
hook-rev.py
中构造修订字符串并写出Python文件,例如buildrev.py
包含修订字符串到变量的分配rev.py
中使用import buildrev
并定义返回get_rev()
的{{1}} 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
(由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
。