# 打包与分发 > T-524 目标:先把当前 Windows 桌面工具打成免安装 onedir `.exe`,方便第一版交付使用。暂不做自动更新器、安装器、增量补丁或在线升级。 ## 一、打包前提 - 在 Windows 环境执行。 - Python 环境已能运行源码版 `python main.py`。 - 打包脚本固定使用 Windows Python Launcher 的 `py -3.10`,不使用当前 PATH 中的 `python`;正式出包前先确认 `py -3.10 --version` 可用。 - 安装运行依赖和打包依赖: ```powershell py -3.10 -m pip install -r requirements-build.txt ``` `requirements-build.txt` 会先安装 `requirements.txt` 的运行依赖,再安装 PyInstaller。依赖必须安装到 Python 3.10 环境里,避免 PATH 上的 Python 3.7/3.12/3.14 打出不可比对的包。 ## 二、打包命令 ```powershell powershell -ExecutionPolicy Bypass -File scripts\build_exe.ps1 ``` 脚本会执行: ```powershell py -3.10 -m PyInstaller --noconfirm --clean cmshopee.spec ``` 成功后输出: ```text dist\cmshopee\ cmshopee.exe _internal\ ``` 正式分发入口是 `release\cmshopee--portable.zip`。`dist\cmshopee\` 只是 PyInstaller 构建中间产物,不直接作为正式发包名称。 当前 `requirements-build.txt` 锁定 PyInstaller 6.11.1,onedir 产物必须是 `cmshopee.exe` + `_internal\` 集中依赖布局。`scripts\build_exe.ps1` 会校验 `_internal\` 存在;缺失时直接失败,避免把不一致的打包环境误发给用户。 发布包只包含程序文件和依赖文件: ```text cmshopee\ cmshopee.exe _internal\ ``` 首次运行后才会在同级生成 `data\`,用于保存用户本地数据。 ## 三、版本号与发布目录 参考 `D:\chengma\cmbot` 的打包方式,版本控制采用“单一版本源 + 发布目录带版本号”的轻量方案,暂不引入启动器、自动更新或 manifest。 ### 3.1 单一版本源 新增 `app/version.py`,作为软件名称和版本号的唯一来源: ```python APP_NAME = "蝦皮圈優化助手" APP_CODE_NAME = "cmshopee" APP_VERSION = "0.1.0" ``` 规则: - 修改版本号只改 `app/version.py` 的 `APP_VERSION`。 - GUI 窗口标题读取同一版本源,显示为 `蝦皮圈優化助手 v0.1.0`。 - 打包脚本读取同一版本源生成发布目录、压缩包和 `version.txt`。 - 禁止在 GUI、构建脚本或文档示例之外重复硬编码不同版本号。 ### 3.2 发布目录结构 `scripts\build_exe.ps1` 仍先产出 PyInstaller 原始目录 `dist\cmshopee\`,再组装面向用户分发的 `release\` 目录: ```text release\ cmshopee-0.1.0\ cmshopee.exe _internal\ version.txt README.txt cmshopee-0.1.0-portable.zip ``` 说明: - `dist\cmshopee\` 是构建中间产物,不直接作为正式发包名称。 - `release\cmshopee-\` 是人工验收和分发目录。 - `release\cmshopee--portable.zip` 是交付给用户的便携压缩包。 - `version.txt` 使用 ASCII/UTF-8 无 BOM 写入 `APP_VERSION`,用于人工排查和未来更新机制读取。 - `README.txt` 用中文写明启动方式、不要放入 `Program Files`、保留 `data\`、升级时覆盖程序文件但不覆盖 `data\`。 当前 PyInstaller 6.11.1 的 onedir 为集中依赖结构,所以 `release\cmshopee-\` 必须包含 `cmshopee.exe` 和 `_internal\`,不得只复制单个 exe。 ### 3.3 正式出包流程 1. 修改 `app/version.py` 中的 `APP_VERSION`。 2. 运行语法检查和单元测试。 3. 运行 `powershell -ExecutionPolicy Bypass -File scripts\build_exe.ps1`。 4. 检查 `release\cmshopee-\version.txt`、GUI 标题栏版本、压缩包文件名三者一致。 5. 在无 Python 环境的 Windows 10/11 机器上解压 `cmshopee--portable.zip` 并启动验证。 正式发布构建固定使用 Python 3.10。源码在 Python 3.7.9 上曾验证可运行,但发布包不再以 3.7.9 作为打包基线;脚本会直接调用 `py -3.10` 并校验返回版本必须是 `3.10.x`,避免同一个 `APP_VERSION` 在不同 Python 版本下打出不可比对的包。CI 仍可继续使用 Python 3.11 做自动测试。 ### 3.4 暂不引入自动更新 本阶段不迁移 `cmbot` 的 `Launcher.exe`、`manifest.json`、SHA-256 下载校验、强制更新或在线更新机制。原因: - 当前用户已验证“拷贝发布目录到无 Python 环境运行”的第一版交付路径。 - `cmshopee` 刚完成 `data\` 数据隔离,先把手动发版和版本号一致性做稳。 - 自动更新需要安装根可写、下载暂存、目录切换、回滚和安全校验,属于独立后续任务,不能混入当前打包版本号控制。 后续如果要做在线更新,再另起任务,参考 `cmbot` 的 `Launcher.exe + app\ + manifest.json + sha256 + version.txt` 设计。 ## 四、绝不打包的本地数据 发布包里不能包含以下本地数据、密钥、业务数据或登录态: - `config.json` - `config/ai_models.json` - `cmshopee.db`、`cmshopee.db-wal`、`cmshopee.db-shm` - `db.sqlite` - `chrome_user_data_dir/` - `images/` - `logs/` - `prompts/` - `title_prompt.txt` - `data/` - 运营填写后的 Excel 文件 `cmshopee.spec` 不声明任何 `datas`;`scripts/build_exe.ps1` 会在打包后检查 `dist\cmshopee\`,如果发现上述路径会直接失败。 ## 五、首次运行与本地数据位置 T-538 后,打包版不再把全进程工作目录切到 `cmshopee.exe` 所在目录;路径由 `app/appconfig.py` 按显式数据根解析。 首次运行时,程序会在 exe 同级创建单独的 `data\` 子目录,并把所有用户本地数据放进去: ```text cmshopee\ cmshopee.exe _internal\ data\ config.json config\ ai_models.json cmhub.json cmshopee.db chrome_user_data_dir\ images\ logs\ prompts\ title_prompt.txt ``` 源码运行时同理使用项目根目录下的 `data\`。`config.json` 内的 `user_data_root`、`image_dir`、`db_path` 默认仍保存为 `chrome_user_data_dir`、`images`、`cmshopee.db` 等相对值,运行时再解析到 `data\` 下,保持便携。 这些文件属于用户本地数据,不随新版本程序包覆盖。 ### 旧布局迁移 如果用户从 T-524 旧包升级,新版首次启动会检查 exe 顶层是否存在旧布局数据,例如 `config.json`、`config\`、`cmshopee.db`、`chrome_user_data_dir\`、`images\`、`logs\`、`prompts\`、`title_prompt.txt`。若 `data\` 中没有同名目标,程序会自动移动到 `data\` 下。 如果旧布局和 `data\` 中同时存在同名数据,程序不会覆盖,会以“数据迁移冲突”提示用户先手动合并或备份,避免误丢账号、任务、图片或登录态。此类冲突不是目录不可写,不应直接归类为“数据目录不可写”。 启动时会检测 `data\` 是否可写;如果程序放在 `Program Files` 等只读目录导致写入失败,才会以“数据目录不可写”提示“请把程序放到可写目录,勿放 Program Files”并退出。 ## 六、用户后续更新方式 第一版不做自动更新。给用户发新版本时: 1. 让用户先关闭 cmshopee。 2. 建议用户备份当前整个程序文件夹。 3. 解压新版 `release\cmshopee--portable.zip`。 4. 覆盖新版程序文件和依赖文件。当前 PyInstaller 6.11.1 是 `cmshopee.exe` + `_internal\` onedir,不能只覆盖 `cmshopee.exe`;应把新版 `cmshopee.exe`、`_internal\`、`version.txt`、`README.txt` 等程序文件整体覆盖到旧程序目录。 5. 保留旧目录里的 `data\`,不要删除、覆盖或合并它。 如果用户把整个旧目录删除再放新版,`data\` 里的账号、任务记录、图片和登录态也会一起丢失,只能从备份恢复。 ## 七、验证清单 打包前后至少执行: ```powershell py -3.10 -m compileall app main.py py -3.10 -m unittest discover -s tests powershell -ExecutionPolicy Bypass -File scripts\build_exe.ps1 ``` 打包成功后确认: - `dist\cmshopee\cmshopee.exe` 存在。 - 当前 PyInstaller 6.11.1 下 `dist\cmshopee\_internal\` 必须存在。 - `dist\cmshopee\` 中没有第四节列出的本地数据,尤其不能含 `data\`。 - `release\cmshopee-\version.txt`、GUI 标题栏版本、压缩包文件名三者一致。 - 在干净目录首次启动时能生成 `data\config.json` 并进入 GUI。 - 在目标 Windows 10/11 机器或虚拟机上启动 release exe 后,主窗口标题栏完整可见,左边缘不出屏,用户能用标题栏拖动窗口;小分辨率环境不得出现窗口卡在左上角且标题栏不可拖动的问题(见 T-541)。 涉及 Shopee/CDP 的真实更新能力,仍按任务文档要求用测试商品做人工回归;打包任务本身不新增自动绕过登录、验证码或风控的能力。