Really late to the discussion, but just encountered the same problem and this is the sollution I came to in the end.
Use .spec
files for generating your executable. .spec
files are actually interpreted as python files and you can include your own code for setting up PyInstaller settings.
Make a function that lists all of your hiddenimports
. For my use case, I used dynamic imports from folders in the project, but you can use the same idea and other code to list all modules you need. This is how my .spec
file looks like:
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
# Generate list of hidden imports
import os
def list_python_files(dir_name):
file_list = []
for filename in os.listdir(dir_name):
if filename.endswith('.py'):
file_list.append(f"{dir_name}.{filename[:-3]}")
return file_list
hiddenimports = list_python_files('folder_name_here')
a = Analysis(
['app.py'],
pathex=[],
binaries=[],
datas=[('icon.ico', '.')],
hiddenimports=hiddenimports,
hookspath=[],
hooksconfig={},
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,
[('v', None, 'OPTION')],
exclude_binaries=False, # changed to False
name='app',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=False,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon='icon.ico',
)
coll = COLLECT(
exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='app',
)
pathlib
instead ofos
andos.path
functions to deal with path and file names. Also this example only works with a single non nested package in the current working directory where each module is a*.py
file. System wide installed nested packages maybe with modules implemented in C will need some additional code. – Orangery