# -*- mode: python ; coding: utf-8 -*- import os import sys from PyInstaller.utils.hooks import collect_all, collect_submodules, collect_dynamic_libs block_cipher = None # 获取项目根目录的绝对路径 root_dir = os.path.abspath(SPECPATH) # 收集 UI 目录下的所有子模块 ui_hiddenimports = collect_submodules('UI') # 收集 tkinter 的所有内容(数据文件、二进制、子模块) tkinter_datas = [] tkinter_binaries = [] tkinter_hiddenimports = [] try: from PyInstaller.utils.hooks import collect_all tk_datas, tk_binaries, tk_hiddenimports = collect_all('tkinter') tkinter_datas.extend(tk_datas) tkinter_binaries.extend(tk_binaries) tkinter_hiddenimports.extend(tk_hiddenimports) print(f"Collected tkinter: {len(tk_datas)} datas, {len(tk_binaries)} binaries, {len(tk_hiddenimports)} hiddenimports") except Exception as e: print(f"Warning: Could not collect tkinter: {e}") # 如果自动收集失败,手动添加 tkinter_hiddenimports = ['tkinter', 'tkinter.ttk', '_tkinter', 'tkinter.constants'] # 收集 SSL 相关的动态库 ssl_datas = [] ssl_binaries = [] try: # 收集 pymodbus 的所有依赖 pymodbus_datas, pymodbus_binaries, pymodbus_hiddenimports = collect_all('pymodbus') ssl_datas.extend(pymodbus_datas) ssl_binaries.extend(pymodbus_binaries) except: pymodbus_hiddenimports = [] try: # 收集 ssl 模块的依赖 import ssl as ssl_module ssl_path = os.path.dirname(ssl_module.__file__) # 添加 Python 安装目录下的 DLLs python_dir = os.path.dirname(sys.executable) dll_dir = os.path.join(python_dir, 'DLLs') # 查找并添加 SSL 相关的 DLL 文件 for dll_name in ['libcrypto-1_1-x64.dll', 'libssl-1_1-x64.dll', 'libcrypto-3-x64.dll', 'libssl-3-x64.dll']: dll_path = os.path.join(dll_dir, dll_name) if os.path.exists(dll_path): ssl_binaries.append((dll_path, '.')) print(f"Found SSL DLL: {dll_path}") # 检查 Conda 环境的 Library/bin 目录 conda_prefix = os.environ.get('CONDA_PREFIX') if conda_prefix: conda_dll_dir = os.path.join(conda_prefix, 'Library', 'bin') if os.path.exists(conda_dll_dir): for dll_name in ['libcrypto-1_1-x64.dll', 'libssl-1_1-x64.dll', 'libcrypto-3-x64.dll', 'libssl-3-x64.dll']: dll_path = os.path.join(conda_dll_dir, dll_name) if os.path.exists(dll_path): ssl_binaries.append((dll_path, '.')) print(f"Found Conda SSL DLL: {dll_path}") # 添加 _ssl.pyd 和 _hashlib.pyd for pyd_name in ['_ssl.pyd', '_hashlib.pyd']: pyd_path = os.path.join(dll_dir, pyd_name) if os.path.exists(pyd_path): ssl_binaries.append((pyd_path, '.')) print(f"Found PYD: {pyd_path}") except Exception as e: print(f"Warning: Could not collect SSL binaries: {e}") a = Analysis( ['dtmgtApp.py'], pathex=[root_dir], binaries=ssl_binaries + tkinter_binaries, # 添加 tkinter 二进制文件 datas=[ # 包含 web 资源文件 ('web', 'web'), # 包含整个 UI 目录 ('UI', 'UI'), # 包含数据库文件 ('db', 'db'), # 添加 SSL 数据文件 *ssl_datas, # 添加 tkinter 数据文件 *tkinter_datas, ], hiddenimports=[ # Flask 和相关依赖 'flask', 'flask_cors', 'eel', # PyQt5 相关 'PyQt5', 'PyQt5.QtCore', 'PyQt5.QtGui', 'PyQt5.QtWidgets', 'PyQt5.QtSql', # SSL 和加密相关 'ssl', '_ssl', 'hashlib', '_hashlib', # UI 模块(使用自动收集) *ui_hiddenimports, # pymodbus 相关(使用自动收集) *pymodbus_hiddenimports, # tkinter 相关(使用自动收集,包括所有子模块) *tkinter_hiddenimports, 'tkinter', 'tkinter.ttk', '_tkinter', 'tkinter.constants', 'tkinter.filedialog', # 其他依赖 'websockets', 'serial', 'pymodbus', 'pymodbus.client', 'pymodbus.client.serial', 'pymodbus.client.tcp', 'pymodbus.transport', 'pymodbus.transport.transport', 'keyboard', 'sqlite3', 'multiprocessing', 'api_route', 'dtMachineService', 'modbus_server', 'utils', 'Observable', 'mhi_plc', 'modbus_plc', 'dtMachine_modbus', 'dtMachine_mhi', ], hookspath=[], hooksconfig={}, runtime_hooks=[], excludes=[ # 排除 macOS 相关模块 'serial.tools.list_ports_osx', # 排除不需要的 SQL 驱动(保留 SQLite) 'PyQt5.QtDBus', ], win_no_prefer_redirects=False, win_private_assemblies=False, cipher=block_cipher, noarchive=False, ) pyz = PYZ(a.pure) # 过滤掉不需要的 PyQt5 SQL 驱动插件(保留 SQLite) a.binaries = [x for x in a.binaries if not ( 'qsqlpsql' in x[0] or # PostgreSQL 驱动 'qsqlmysql' in x[0] or # MySQL 驱动 'qsqlodbc' in x[0] # ODBC 驱动 )] exe = EXE( pyz, a.scripts, a.binaries, a.datas, [], name='dtmgtApp-debug', # 调试版本 debug=False, bootloader_ignore_signals=False, strip=False, upx=True, upx_exclude=[], runtime_tmpdir=None, console=True, # 显示CMD窗口(调试用) disable_windowed_traceback=False, argv_emulation=False, target_arch=None, codesign_identity=None, entitlements_file=None, icon=None, )