Issue with PyInstaller Not Including Cryptodome.xxx~ Module #8143
-
Hello, I am encountering an issue with PyInstaller where it does not seem to include the Cryptodome.Random module from pycryptodomex in the final executable. I am using Windows 10, Python 3.11.2, and the most recent version of PyInstaller and pycryptodomex. Environment Issue Description The usual error looks something along the lines of: Traceback (most recent call last):
File "runner.py", line 5, in <module>
File "PyInstaller\loader\pyimod02_importers.py", line 419, in exec_module
File "internal_task_scheduler.py", line 14, in <module>
File "C:\Users\**blocked**~1\AppData\Local\Temp\_MEI146762\utils\apis\auth_db_api_client.py", line 4, in <module>
from utils.apis.api_requests import APIRequester
File "C:\Users\**blocked**~1\AppData\Local\Temp\_MEI146762\utils\apis\api_requests.py", line 11, in <module>
import utils.security as s
File "C:\Users\**blocked**~1\AppData\Local\Temp\_MEI146762\utils\security.py", line 3, in <module>
from Cryptodome.Random import get_random_bytes # isort:skip
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ModuleNotFoundError: No module named 'Cryptodome.Random'
[10472] Failed to execute script 'runner' due to unhandled exception... What I've Tried
The hook file looks like this: import glob
import os
from PyInstaller.compat import EXTENSION_SUFFIXES
from PyInstaller.utils.hooks import get_module_file_attribute
# Include the modules as binaries in a subfolder named like the package.
# Cryptodome's loader expects to find them inside the package directory for
# the main module. We cannot use hiddenimports because that would add the
# modules outside the package.
binaries = []
binary_module_names = [
"Cryptodome.Cipher",
"Cryptodome.Hash",
"Cryptodome.IO",
"Cryptodome.Math",
"Cryptodome.PublicKey",
"Cryptodome.Random", # the original hook-Cryptodome.py file doesn't have the ~.Random included
"Cryptodome.Util",
]
for module_name in binary_module_names:
m_dir = os.path.dirname(get_module_file_attribute(module_name))
for ext in EXTENSION_SUFFIXES:
module_bin = glob.glob(os.path.join(m_dir, "_*%s" % ext))
for f in module_bin:
binaries.append((f, module_name.replace(".", "/")))
My PyInstaller script: # -*- mode: python ; coding: utf-8 -*-
# pylint: disable = missing-module-docstring
from os.path import join as join
from PyInstaller.building.api import EXE, PYZ
from PyInstaller.building.build_main import Analysis
from PyInstaller.config import CONF
HOME_DIRECTORY = r"**blocked**" # hidden for privacy
UTILS = join(HOME_DIRECTORY, "utils")
SCRIPTS = join(HOME_DIRECTORY, "scripts")
WORKPATH = join(HOME_DIRECTORY, "build")
CONF["workpath"] = WORKPATH
a = Analysis(
[join(SCRIPTS, "runner.py")],
pathex=[HOME_DIRECTORY],
binaries=[],
datas=[(SCRIPTS, "scripts"), (UTILS, "utils")],
hiddenimports=["httpx", "keyring", "Cryptodome"], # I have tried with and without the "Cryptodome" hidden import
hookspath=[UTILS], # I have verified the hook-Cryptodome.py file exists
hooksconfig={},
runtime_hooks=[],
excludes=[],
noarchive=False,
)
exe = EXE(
PYZ(a.pure),
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name="api",
debug=True,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True,
)
I'm not sure why PyInstaller is failing to include this module in the final build. Has anyone else faced a similar issue, or does anyone have suggestions on what else I could try? P.S. ~ I have tried with Thank you for your assistance! |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
Only the python modules that are part of import tree generated from the entry-point script ( This looks like you have a bunch of .py scripts (that That means listing all required modules (e.g., The hook you have is collecting only extensions, but you're missing extensions and python modules/sub-packages (for example, Try removing your custom hook, and use
|
Beta Was this translation helpful? Give feedback.
Only the python modules that are part of import tree generated from the entry-point script (
runner.py
) undergo import analysis.This looks like you have a bunch of .py scripts (that
runner.py
presumably invokes somehow) inscripts
and python code inutils
that you smuggle into your frozen application as data files, meaning that no analysis is done on them. So you'll need to deal with all of their imports as hidden imports.That means listing all required modules (e.g.,
hiddenimports=['Cryptodome.Random', 'Cryptodome.Hash', ...]
) and not just top-level package names - adding top-level package name to hidden imports does not automatically c…