使用gmsh导入从Python代码创建一个可执行文件



我正试图使用pyinstaller将我的Python包打包成一个可执行文件。脚本名称被称为";运行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 "PyInstallerloaderpyiboot01_bootstrap.py", line 144, in __init__
File "ctypes__init__.py", line 381, in __init__
FileNotFoundError: Could not find module 'C:UserswillberAnaconda3Scriptsgmsh' (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

有没有人试图编译一些导入gmsh包的Python代码?如果可以的话,我真的很感激能提供一个与pyinstaller一起使用的.spec文件示例!

gmsh-python包封装了一堆已编译的库,这些库包含您从python调用的方法的实现。当您将gmsh.py导入到脚本中时,gmsh会在后台加载这些库,从而通过python方法访问它们的功能。因此,将这些库嵌入到pyinstaller输出中是至关重要的,这样您的代码就可以像直接通过python解释器运行代码一样发挥作用。

pyinstaller很难始终如一地找到这些库,因为它们的访问方式与正常的python导入不同,而是使用cytpes包加载的。在文档中有一些关于pyinstaller如何做到这一点的描述。由于在运行编译后的python脚本时会看到dynlib.dll加载错误,这表明pyinstaller在编译过程中找不到gmsh库,因此可执行文件中缺少它。

如果您查看gmsh.py源代码,您可以看到gmsh.py加载了一个名为gmsh-4.9.dll的.dll库(适用于Windows操作系统(。您可以使用pyinstaller.spec文件的binaries输入将编译器指向gmsh-4.9.dll

这里有一个示例.spec文件,它在编译时动态定位gmsh-4.9.dll,以便为您的活动环境选择正确的.dll。你可以通过过滤gmsh目录中的所有*.dll来使其更通用,但为了清晰起见,我已经硬编码了:

# -*- 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,
)

相关内容

最新更新