Reputation: 737
I am trying to convert my code into an exe using pyinstaller spec. Pyinstaller initially failed with the following reason:
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.
I tried to correct it by adding the following line to my pathex list in the spec:
'myenv\\lib\\site-packages\\lightgbm'
Note: myenv is my virtualenv created for this project.
Which led to ImportError for sklearn. I added sklearn to hidden imports. This is my final spec fie:
# -*- 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')
This leads to an error I find very weird:
File "myenv\lib\site-packages\lightgbm\sklearn.py", line 9, in <module>
ImportError: attempted relative import with no known parent package
[12692] Failed to execute script myscript
I have no idea why it would be searching for sklearn.py inside lightgbm?
There is sklearn.py inside lightgbm, but I am not sure how to fix this error. Also, there is no sklearn folder in the dist/myscript folder. Ideally it should have been present. I tried to manually copy the sklearn folder, although, as suspected, it made no difference. Could someone please let me know where the spec file is wrong?
Upvotes: 2
Views: 1277
Reputation: 103
Let's go back to the first error you had. That error suggests lib_lightgbm.dll
was not seen when your application was frozen.
Assuming you run pyinstaller from Windows cmd.exe, you can fix this by passing a hook for lightgbm to pyinstaller, so that it knows where to get it from, e.g.
pyinstaller --additional-hooks-dir dir_with_lightgbm_hook --hidden-import lightgbm myscript.py
The name of the hook should be hook-lightgbm.py
and for its contents, you can look here: https://github.com/pyinstaller/pyinstaller/blob/develop/PyInstaller/hooks/hook-numpy.py , it should be something similar. Just make sure that the library is added to the binaries list, i.e.
binaries.append((os.path.join(os.path.dirname(
get_module_file_attribute('lightgbm')), "lib_lightgbm.dll"), "lightgbm"))
The second "lightgbm"
argument is the location where the .dll will be copied, relative to your distribution directory, so in your case it should end up as dist\myscript\lightgbm\lib_lightgbm.dll
.
Note: Adding lib_lightgbm.dll
through a hook will make pyinstaller add the dependencies for it to the distribution, so it is better to do it like this than just copying it manually.
Second note: When copying your distribution package to another machine, you might need to install the appropriate Visual Studio redistributable used by the library (e.g. VS 2015 redistributable).
EDIT: Forgot to mention that if you do it like this, you can remove the path you added to your pathex.
Upvotes: 2