diff --git a/geo_tool_app.spec b/geo_tool_app.spec new file mode 100644 index 0000000..7cc84d4 --- /dev/null +++ b/geo_tool_app.spec @@ -0,0 +1,217 @@ +# -*- 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, +)