Создайте исполняемый файл из кода Python с помощью импорта gmsh

Я пытаюсь упаковать свой пакет Python в исполняемый файл с помощью pyinstaller. Имя сценария называется "run-jointbuilder.py". Пакет имеет ряд зависимостей (например, numpy), но, что немаловажно, gmsh.

При использовании pyinstaller для компиляции моего кода он кажется успешным, но затем, когда я пытаюсь запустить исполняемый файл, я получаю следующие ошибки:

      import gmsh # PyInstaller PYZ\
import ctypes.util # PyInstaller PYZ\
import 'ctypes.util' # <pyimod03_importers.FrozenImporter object at 0x000001BD783FC910>\
Traceback (most recent call last):\
  File "PyInstaller\loader\pyiboot01_bootstrap.py", line 144, in __init__
  File "ctypes\__init__.py", line 381, in __init__\
FileNotFoundError: Could not find module 'C:\Users\willber\Anaconda3\Scripts\gmsh' (or one of its dependencies). Try using the full path with constructor syntax.

Затем я получаю эту ошибку:

      __main__.PyInstallerImportError: Failed to load dynlib/dll

'C:\\Users\\willber\\Anaconda3\\Scripts\\gmsh'. Most probably this dynlib/dll was not found when the application was frozen.

[18612] Failed to execute script run-jointbuilder

Кто-нибудь пытался скомпилировать код Python, который импортирует пакет gmsh? Я был бы очень признателен за пример файла .spec для использования с pyinstaller, если это так!

1 ответ

Пакет gmsh python включает в себя набор скомпилированных библиотек, которые содержат реализации методов, которые вы вызываете из python. Когда вы импортируете gmsh.py в свой скрипт, gmsh загружает эти библиотеки в фоновом режиме, предоставляя вам доступ к их функциям с помощью методов python. Поэтому важно, чтобы эти библиотеки были встроены в вывод pyinstaller, чтобы ваш код работал так, как если бы вы запускали его напрямую через интерпретатор python.

Для pyinstaller сложно постоянно находить эти библиотеки, поскольку к ним не обращаются так же, как к обычному импорту python, они загружаются с использованием пакета cytpes. Там какое - то описание того , как pyinstaller делает это в документации . Поскольку вы видите ошибку загрузки dynlib / dll при запуске скомпилированного скрипта python, это говорит о том, что pyinstaller не находит библиотеку gmsh во время компиляции и, следовательно, отсутствует в исполняемом файле.

Если вы посмотрите в исходный код gmsh.py , вы увидите, что gmsh.py загружает библиотеку .dll, которая называется для ОС Windows. Вы можете использовать binaries ввод файла .spec pyinstaller, чтобы указать компилятору на.

Вот пример файла .spec, который динамически определяет местонахождение gmsh-4.9.dllво время компиляции, поэтому он подбирает правильную .dll для вашей активной среды. Вы можете сделать это более общим, отфильтровав все * .dll в каталоге gmsh, но для ясности я жестко запрограммировал:

      # -*- mode: python ; coding: utf-8 -*-
from pathlib import Path
import gmsh

# get the location of the gmsh dll which sits next to the gmsh.py file
libname = 'gmsh-4.9.dll'
libpath = Path(gmsh.__file__).parent / libname
print('Adding {} to binaries'.format(libpath))

block_cipher = None

a = Analysis(['gmsh-test.py'],
         pathex=['C:\\Users\\user\\dev\\gmsh'],
         # tell pyinstaller to add the binary to the compiled path
         binaries=[(str(libpath), '.')],
         datas=[],
         hiddenimports=[],
         hookspath=[],
         runtime_hooks=[],
         excludes=[],
         win_no_prefer_redirects=False,
         win_private_assemblies=False,
         cipher=block_cipher,
         noarchive=False)

pyz = PYZ(a.pure, a.zipped_data,
         cipher=block_cipher)

exe = EXE(pyz,
      a.scripts,
      a.binaries,
      a.zipfiles,
      a.datas,
      name='gmsh-test',
      debug=False,
      bootloader_ignore_signals=False,
      strip=False,
      upx=True,
      console=True,
      runtime_tmpdir=None,
      )
Другие вопросы по тегам