Files
ChouJuGEO/geo_tool_app.spec
T

218 lines
6.3 KiB
RPMSpec
Raw Normal View History

2026-05-30 13:03:42 +08:00
# -*- 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"),
("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 大量使用动态 importscriptrunner.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",
2026-05-30 15:39:42 +08:00
"tomli_w",
# ---- Streamlit 内部依赖(动态子模块多,显式声明)----
"altair",
"pydeck",
2026-05-30 13:03:42 +08:00
]
# ── 排除不必要的包(减小体积) ──────────────────────────────────
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,
)