Pyinstaller exe 转换失败 - 使用 lightgbm 和 sklearn



我正在尝试使用pyinstaller规范将我的代码转换为exe。 Pyinstaller最初失败,原因如下:

main__.PyInstallerImportError: Failed to load dynlib/dll 
'C:\Users\...\lightgbm\../compile\lib_lightgbm.dll'. Most probably this 
dynlib/dll was not found when the application was frozen.

我试图通过将以下行添加到规范中的 pathex 列表中来更正它:

'myenv\lib\site-packages\lightgbm'

注意:myenv 是我为这个项目创建的虚拟环境。

这导致了 sklearn 的 ImportError。我将 sklearn 添加到隐藏的导入中。这是我的最终规格:

# -*- mode: python -*-
import sys
sys.setrecursionlimit(5000)
block_cipher = None

a = Analysis(['myscript.py'],
pathex=['C:\project_folder', 'myenv\lib\site-packages\lightgbm'],
binaries=[],
datas=[('lib_lightgbm.dll', '.')],
hiddenimports=['cython', 'sklearn', 'sklearn.feature_extraction','sklearn.pipeline', 'sklearn.ensemble', 'sklearn.neighbors.typedefs', 'sklearn.neighbors.quad_tree', 'sklearn.tree._utils'],
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,
[],
exclude_binaries=True,
name='myscript',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=True )
coll = COLLECT(exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
name='myscript')

这导致了一个我觉得很奇怪的错误:

File "myenvlibsite-packageslightgbmsklearn.py", line 9, in <module>
ImportError: attempted relative import with no known parent package
[12692] Failed to execute script myscript

我不知道为什么它会在 lightgbm 中搜索 sklearn.py?lightgbm 内部有 sklearn.py,但我不确定如何解决此错误。此外,dist/myscript 文件夹中没有 sklearn 文件夹。理想情况下,它应该存在。我试图手动复制 sklearn 文件夹,尽管正如怀疑的那样,它没有区别。有人可以让我知道规范文件哪里有问题吗?

让我们回到你遇到的第一个错误。该错误表明在应用程序被冻结时未看到lib_lightgbm.dll

假设您从 Windows cmd.exe 运行 pyinstaller,您可以通过将 lightgbm 的钩子传递给 pyinstaller 来解决此问题,以便它知道从哪里获取它,例如

pyinstaller --additional-hooks-dir dir_with_lightgbm_hook --hidden-import lightgbm myscript.py

钩子的名称应该是hook-lightgbm.py的,对于它的内容,你可以在这里看:https://github.com/pyinstaller/pyinstaller/blob/develop/PyInstaller/hooks/hook-numpy.py,它应该是类似的。只需确保将库添加到二进制文件列表中,即

binaries.append((os.path.join(os.path.dirname(
get_module_file_attribute('lightgbm')), "lib_lightgbm.dll"), "lightgbm"))

第二个"lightgbm"参数是相对于分发目录复制.dll的位置,因此在您的情况下,它应该以distmyscriptlightgbmlib_lightgbm.dll结尾。

注意:通过钩子添加lib_lightgbm.dll将使 pyinstaller 将它的依赖项添加到发行版中,因此最好这样做,而不是手动复制它。

第二点注意:将分发包复制到另一台计算机时,可能需要安装库使用的相应 Visual Studio 可再发行组件(例如 VS 2015 可再发行组件)。

编辑:忘了提到,如果你这样做,你可以删除你添加到你的pathex的路径。