Я пытаюсь получить выходные данные git describe
description, оцененные на этапе анализа PyInstaller, и сделать их доступными для переменной времени выполнения Python, чтобы предоставить приложению строку ревизии, полученную из среды сборки и отображаемую во время выполнения.
Я полагаю, что для этого лучше всего использовать хуков PyInstaller, поскольку они позволяют выполнять произвольный код Python в файле хуков, пока он строит дерево импорта. Однако я не нашел способа передать значение переменной из фазы анализа PyInstaller в переменную времени выполнения, чтобы оно могло отображаться приложением, работающим как сгенерированный файл .exe
.
Пример: файл hook-rev.py
который импортируется механизмом анализа PyInstaller при обнаружении import rev
:
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, а оператор print показывает, что правильный результат git describe
назначен переменной rev
в области действия файла подключения, когда PyInstaller создает дерево импорта. Но сгенерированный файл .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
не известен во время выполнения.
Есть ли другой способ соединить пространства имен между средой выполнения и обработкой импорта хуков PyInstaller?
Для справки, вот способ достижения требуемой функциональности. Это не идеальное решение, потому что оно опирается на два дополнительных файла 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, что может быть неточным. buildrev.py
не должен отслеживаться VCS.