Pyinstaller未加载DLL


问题内容

在为我的python脚本构建exe后dungeon.py,当PyBearLibTerminal.py(程序导入的脚本)尝试加载DLL时出现错误BearLibTerminal.dll。该脚本运行良好,它仅运行导致该错误的可执行文件。运行可执行文件时报告的错误是

[3464] Failed to execute script dungeon
Traceback (most recent call last):
  File "dungeon.py", line 2, in <module>
  File "<frozen importlib._bootstrap>", line 2237, in _find_and_load
  File "<frozen importlib._bootstrap>", line 2226, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 1200, in _load_unlocked
  File "<frozen importlib._bootstrap>", line 1129, in _exec
  File "C:\Program Files\Python34\lib\site-packages\PyInstaller\loader\pyimod03_importers.py", line 631, in exec_module
    exec(bytecode, module.__dict__)
  File "PyBearLibTerminal.py", line 50, in <module>
RuntimeError: BearLibTerminal library cannot be loaded.

PyBearLibTerminal.py是导致错误的文件的开头。

import sys, ctypes, numbers, os

_version3 = sys.version_info >= (3, 0)

_library = None
_possible_library_names = [
    'BearLibTerminal.dll',        # Generic Windows DLL
    './libBearLibTerminal.so',    # Local Linux SO
    './libBearLibTerminal.dylib', # Local OS X dylib
    './BearLibTerminal.so',       # Local Linux SO w/o prefix
    'libBearLibTerminal.so',      # System Linux SO
    'libBearLibTerminal.dylib',   # System OS X dylib
    'BearLibTerminal.so'          # System Linux SO w/o prefix 
]

ctypes.windll.kernel32.SetDllDirectoryW(os.getcwd().replace('\\', '/'))

for name in _possible_library_names:
    try:
        _library = ctypes.CDLL(name)
        break
    except OSError:
        continue

if _library is None:
    raise RuntimeError("BearLibTerminal library cannot be loaded.")

最后,这是我的dungeon.spec文件:

# -*- mode: python -*-

block_cipher = None


a = Analysis(['dungeon.py'],
             pathex=['C:\\Users\\Brett\\Documents\\Projects\\Spark'],
             binaries=[('BearLibTerminal.dll', '.')],
             datas=[('enemies.json', '.'), ('items.json', '.'), ('materials.json', '.'), ('names.json', '.'), ('unifont-8.0.01.ttf', '.')],
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          exclude_binaries=True,
          name='dungeon',
          debug=False,
          strip=False,
          upx=True,
          console=True )
coll = COLLECT(exe,
               a.binaries,
               a.zipfiles,
               a.datas,
               strip=False,
               upx=True,
               name='dungeon')

问题答案:

1)检查dist /文件夹(或.exe所在的任何文件夹),以确保BearLibTerminal.dll存在并且可以访问。如果您的.exe不存在,它将无法运行

2)接下来检查依赖关系。它不一定能找到BearLibTerminal.dll,但不能找到BearLibTerminal.dll所依赖的事实。如果您的计算机上安装了Visual
Studio,请使用dumpbin来确定DLL所依赖的内容。(在此处安装了Dumpbin C:\ Program Files(x86)\ Microsoft
Visual Studio 14.0 \ VC \ bin \ dumpbin.exe)

dumpbin /DEPENDENTS your.dll

这将列出BearLibTerminal.dll所依赖的DLL。如果适用,请确保将它们包含在与exe相同的目录中(例如,kernel32.dll不需要在该目录中)

3)如果您没有Visual
Studio或dumpbin,请下载http://www.dependencywalker.com/,它将完成相同的操作

4)如果您确定所有DLL及其依赖的DLL都已考虑在内,请检查您的spec文件以确保其格式正确。如果在运行pyinstaller时显示一堆警告,可能会导致问题。尤其是在Windows
10上(它们不能很好地发挥作用:https
:
//github.com/pyinstaller/pyinstaller/issues/1566)

5)如果BearLibTerminal.dll是您自己编译的dll,请确保它是在发布模式下构建的,并且您的C / C ++代码生成运行时库为/
MT(多线程)

6)确保您也拥有最新版本的pyinstaller。

它提供了大量信息,但是希望它可以帮助您解决问题。我本人正在处理同一问题。