【问题标题】:Create an executable from Python code with gmsh import使用 gmsh import 从 Python 代码创建可执行文件
【发布时间】:2021-08-02 02:03:28
【问题描述】:

我正在尝试使用 pyinstaller 将我的 Python 包打包成可执行文件。脚本名叫做“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

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

【问题讨论】:

    标签: python compiler-errors pyinstaller gmsh


    【解决方案1】:

    gmsh python 包包装了一堆编译的库,其中包含您从 python 调用的方法的实现。当您将 gmsh.py 导入脚本时,gmsh 会在后台加载这些库,让您可以通过 python 方法访问它们的功能。因此,必须将这些库嵌入到 pyinstaller 输出中,这样您的代码才能像直接通过 python 解释器运行它时一样运行。

    pyinstaller 很难始终如一地找到这些库,因为它们的访问方式与普通 python 导入不同,它们是使用 cytpes 包加载的。有一些描述 pyinstaller 如何做到这一点in the docs。由于您在运行已编译的 python 脚本时看到 dynlib/dll 加载错误,这表明 pyinstaller 在编译期间没有找到 gmsh 库,因此可执行文件中缺少它。

    如果您查看gmsh.py source,您可以看到gmsh.py 为Windows 操作系统加载了一个名为gmsh-4.9.dll 的.dll 库。您可以使用 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,
          )
    

    【讨论】:

    • 太棒了,谢谢好心的陌生人!正是我一直在寻找的!我欠你四包啤酒!
    猜你喜欢
    • 2016-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-14
    • 2017-08-23
    • 2013-05-20
    • 1970-01-01
    相关资源
    最近更新 更多