207 lines
6.0 KiB
Python
207 lines
6.0 KiB
Python
# -*- 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',
|
||
|
||
# openpyxl 相关(Excel导出功能)
|
||
'openpyxl',
|
||
'openpyxl.styles',
|
||
'openpyxl.utils',
|
||
'openpyxl.cell',
|
||
'openpyxl.worksheet',
|
||
'openpyxl.workbook',
|
||
'openpyxl.reader',
|
||
'openpyxl.writer',
|
||
'et_xmlfile',
|
||
|
||
# 其他依赖
|
||
'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=False,
|
||
bootloader_ignore_signals=False,
|
||
strip=False,
|
||
upx=True,
|
||
upx_exclude=[],
|
||
runtime_tmpdir=None,
|
||
console=False, # 隐藏CMD窗口,日志输出已重定向到文件
|
||
disable_windowed_traceback=False,
|
||
argv_emulation=False,
|
||
target_arch=None,
|
||
codesign_identity=None,
|
||
entitlements_file=None,
|
||
icon=None, # 可以添加ico图标
|
||
)
|