# -*- mode: python ; coding: utf-8 -*- """ PyInstaller 打包配置文件 — GEO Tool 打包模式:单文件 (EXE),兼容 macOS / Windows """ import sys from pathlib import Path # PyInstaller 工具函数:收集包元数据和资源 from PyInstaller.utils.hooks import copy_metadata, collect_data_files, collect_all block_cipher = None # ── 资源文件列表 ────────────────────────────────────────────── # 格式: (源路径, 目标路径 in MEIPASS) # 目录会被递归包含 datas = [ ("geo_tool.py", "."), ("config.json", "."), ("geo_data.db", "."), (".streamlit", ".streamlit"), ("knowledge_base", "knowledge_base"), ("modules", "modules"), ("platform_sync", "platform_sync"), ] # ── 收集包的 dist-info/METADATA ────────────────────────────── # 很多包在运行时通过 importlib.metadata.version(name) 获取版本号, # PyInstaller 单文件模式不会自动包含这些元数据,需显式收集。 _METADATA_PACKAGES = [ "streamlit", "pandas", "plotly", "langchain_core", "langchain_deepseek", "langchain_openai", "langchain_groq", "langchain_moonshot", "langchain_community", "dashscope", "httpx", "pyperclip", "watchdog", "importlib_metadata", ] for _pkg in _METADATA_PACKAGES: try: datas += copy_metadata(_pkg) except Exception: pass # 包未安装时静默跳过 # ── Streamlit 全量收集(子模块 + 数据 + 动态库)──────────── # Streamlit 大量使用动态 import(scriptrunner.magic_funcs 等), # 必须用 collect_all 确保所有子模块都被找到。 try: _st_datas, _st_binaries, _st_hidden = collect_all("streamlit") datas += _st_datas binaries += _st_binaries hiddenimports += _st_hidden except Exception: pass # ── 其他包的静态 / 数据文件 ────────────────────────────────── _DATAFILE_PACKAGES = [ "plotly", # plotly.min.js "altair", # vega-lite schemas "pandas", # JSON schemas "pyarrow", # dataset discovery files "langchain_core", # prompt templates ] for _pkg in _DATAFILE_PACKAGES: try: datas += collect_data_files(_pkg) except Exception: pass # ── 显式隐式导入 ────────────────────────────────────────────── # PyInstaller 可能无法自动发现的动态 / 延迟导入 hiddenimports = [ # ---- 应用模块 ---- "modules", "modules.data_storage", "modules.keyword_tool", "modules.roi_analyzer", "modules.knowledge_base", "modules.keyword_mining", "modules.semantic_expander", "modules.topic_cluster", "modules.content_scorer", "modules.eeat_enhancer", "modules.fact_density_enhancer", "modules.optimization_techniques", "modules.schema_generator", "modules.technical_config_generator", "modules.multimodal_prompt", "modules.workflow_automation", "modules.negative_monitor", "modules.resource_recommender", "modules.config_optimizer", "modules.content_metrics", "modules.keyword_data_enhancer", "modules.content_uniqueness", "modules.ai_search_verifier", "modules.llm_factory", "modules.chat_doubao", "modules.ui", "modules.ui.state", "modules.ui.theme", "modules.ui.components", "modules.ui.tab_keywords", "modules.ui.tab_autowrite", "modules.ui.tab_optimize", "modules.ui.tab_validation", "modules.ui.tab_history", "modules.ui.tab_reports", "modules.ui.tab_workflow", "modules.ui.tab_resources", "modules.ui.tab_platform_sync", "modules.ui.tab_config_optimizer", "modules.ui.tab_knowledge", "modules.services", "modules.services.schema_service", "modules.services.tech_config_service", "platform_sync", "platform_sync.base_publisher", "platform_sync.github_publisher", "platform_sync.copy_manager", # ---- LangChain 生态系统 ---- "langchain_core", "langchain_core.prompts", "langchain_core.output_parsers", "langchain_core.language_models", "langchain_deepseek", "langchain_openai", "langchain_groq", "langchain_moonshot", "langchain_community", "langchain_community.chat_models", "dashscope", # ---- 数据 / 可视化 ---- "pandas", "plotly", "plotly.express", "plotly.graph_objects", # ---- 其他依赖 ---- "pyperclip", "httpx", "watchdog", "sqlite3", "importlib.metadata", "json", "csv", "hashlib", ] # ── 排除不必要的包(减小体积) ────────────────────────────────── excludes = [ "tkinter", "matplotlib", "scipy", "PIL", "cv2", "notebook", "jupyter", "jedi", "ipython", "setuptools", "pdb", "unittest", ] # ── Analysis ────────────────────────────────────────────────── a = Analysis( ["run_bundle.py"], pathex=[], binaries=[], datas=datas, hiddenimports=hiddenimports, hookspath=[], hooksconfig={}, runtime_hooks=[], excludes=excludes, noarchive=False, optimize=0, ) pyz = PYZ(a.pure) # ── 单文件可执行 ────────────────────────────────────────────── # 不同平台自动选择合适输出: # macOS → geo_tool_app (Unix executable) # Windows → geo_tool_app.exe exe = EXE( pyz, a.scripts, a.binaries, a.datas, [], name="geo_tool_app", debug=False, bootloader_ignore_signals=False, strip=False, upx=True, upx_exclude=[], runtime_tmpdir=None, console=True, disable_windowed_traceback=False, argv_emulation=False, target_arch=None, codesign_identity=None, entitlements_file=None, # macOS .app 产物额外配置(仅在 --windowed / console=False 时生效) # bundle_identifier=None, # info_plist=None, )