Как получить доступ к переменным в пространстве имен файлов хука PyInstaller из кода времени выполнения?

1

Я пытаюсь получить выходные данные 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?

Теги:
hook
pyinstaller

1 ответ

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() который возвращает buildrev.rev
  4. В файле приложения получить доступ к строке редакции, вызвав 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.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню