# -*- mode: python ; coding: utf-8 -*- import os import sys from pathlib import Path # 获取项目根目录 project_root = Path(SPECPATH).parent sys.path.insert(0, str(project_root)) # 收集所有Python文件和数据文件 def collect_project_files(): """收集项目文件""" datas = [] # 数据目录 data_dirs = [ 'config', 'data', 'docs', 'migrations', 'VWED任务模块接口文档', 'scripts', 'logs' ] for dir_name in data_dirs: dir_path = project_root / dir_name if dir_path.exists(): for root, dirs, files in os.walk(str(dir_path)): # 跳过__pycache__目录 dirs[:] = [d for d in dirs if d != '__pycache__'] for file in files: if not file.endswith('.pyc'): src_file = os.path.join(root, file) rel_path = os.path.relpath(src_file, str(project_root)) datas.append((src_file, os.path.dirname(rel_path))) # 添加配置文件 config_files = [ 'requirements.txt', 'README.md', 'CLAUDE.md' ] for file_name in config_files: file_path = project_root / file_name if file_path.exists(): datas.append((str(file_path), '.')) return datas # 收集隐藏导入 hiddenimports = [ # Web框架相关 'uvicorn.workers.UvicornWorker', 'uvicorn.protocols.http.auto', 'uvicorn.protocols.websockets.auto', 'uvicorn.lifespan.on', 'uvicorn.loops.auto', 'fastapi.applications', 'fastapi.routing', 'fastapi.middleware', 'fastapi.responses', 'pydantic._internal', 'pydantic.v1', # 数据库相关 'pymysql', 'aiomysql', 'cryptography', 'sqlalchemy.dialects.mysql.pymysql', 'sqlalchemy.dialects.mysql.aiomysql', 'alembic.runtime.migration', 'alembic.operations.ops', # GUI相关 'tkinter', 'tkinter.ttk', 'tkinter.messagebox', 'tkinter.filedialog', # 其他依赖 'loguru', 'croniter', 'pymodbus', 'aiofiles', 'psutil', 'redis', 'aiohttp', 'websockets', 'jsonschema', 'pycryptodome', 'requests', 'configparser', 'pathlib', 'threading', 'subprocess' ] # 集成启动器分析 a = Analysis( [str(project_root / 'packaging' / 'integrated_launcher.py')], pathex=[str(project_root)], binaries=[], datas=collect_project_files(), hiddenimports=hiddenimports, hookspath=[], hooksconfig={}, runtime_hooks=[], excludes=['matplotlib', 'numpy', 'pandas', 'scipy', 'PIL'], win_no_prefer_redirects=False, win_private_assemblies=False, cipher=None, noarchive=False, ) # 生成pyz文件 pyz = PYZ(a.pure, a.zipped_data, cipher=None) # 生成单文件可执行文件 - 后台运行版本 exe = EXE( pyz, a.scripts, a.binaries, a.zipfiles, a.datas, [], name='VWED_Task_System', debug=False, bootloader_ignore_signals=False, strip=False, upx=False, # 禁用UPX压缩,避免DLL问题 upx_exclude=[], runtime_tmpdir=None, console=False, # 禁用控制台窗口,支持后台运行 disable_windowed_traceback=False, argv_emulation=False, target_arch=None, codesign_identity=None, entitlements_file=None, icon=str(project_root / 'packaging' / 'resources' / 'icon.ico') if (project_root / 'packaging' / 'resources' / 'icon.ico').exists() else None, ) # 生成调试版本 - 带控制台窗口 exe_debug = EXE( pyz, a.scripts, a.binaries, a.zipfiles, a.datas, [], name='VWED_Task_System_Debug', debug=True, bootloader_ignore_signals=False, strip=False, upx=False, upx_exclude=[], runtime_tmpdir=None, console=True, # 调试版本保留控制台窗口 disable_windowed_traceback=False, argv_emulation=False, target_arch=None, codesign_identity=None, entitlements_file=None, icon=str(project_root / 'packaging' / 'resources' / 'icon.ico') if (project_root / 'packaging' / 'resources' / 'icon.ico').exists() else None, )