本篇复用上一篇的 tests/、JSON 事件协议和 job_key,把同一 report_job.py 作为 PyInstaller 入口;诊断日志仍可被原有测试解析。上一篇固定复现包成为本篇干净 Windows 虚拟机的验收输入。客户没有 Python 环境时可打成可执行文件,但能启动不等于可交付。
一、程序路径不要依赖当前目录
python
from __future__ import annotations
import json
import sys
from pathlib import Path
def app_dir() -> Path:
if getattr(sys, "frozen", False):
return Path(sys.executable).resolve().parent
return Path(__file__).resolve().parent
CONFIG = app_dir() / "config.json"
LOG_DIR = app_dir() / "logs"
LOG_DIR.mkdir(exist_ok=True)
def main() -> int:
try:
if not CONFIG.is_file():
raise FileNotFoundError(CONFIG)
json.loads(CONFIG.read_text(encoding="utf-8"))
except (OSError, json.JSONDecodeError) as exc:
log = LOG_DIR / "startup-error.log"
log.write_text(f"type={type(exc).__name__}\n", encoding="utf-8")
print(f"startup_failed log={log}")
return 2
print(f"config_ok path={CONFIG}")
return 0
if __name__ == "__main__":
raise SystemExit(main())
输出示例:
text
config C:\Tools\Cleaner\config.json
双击程序时当前目录不固定,因此配置与日志应基于程序位置或用户明确选择的位置。
二、打包命令也要进入版本管理
bash
python -m venv .venv
.venv/Scripts/python -m pip install --require-hashes -r requirements.txt
.venv/Scripts/pyinstaller --onefile --name data-cleaner main.py
运行输出:
text
127 INFO: Building EXE from EXE-00.toc completed successfully.
dist\data-cleaner.exe
依赖锁定、图标、资源文件与构建命令应写入脚本。交付压缩包同时包含示例配置、输入样例、使用说明和校验值。
三、错误窗口不能一闪而过
顶层入口捕获预期异常,把时间、步骤和错误类型写入 UTF-8 日志,并返回非零退出码。日志不得包含密码、Cookie 或完整个人数据。先在干净的 Windows 虚拟机测试,再交给客户小样本验收。
四、为什么打包不等于复制开发环境
单文件程序启动时资源可能先解压到临时目录,而用户双击时当前目录也不确定。代码文件位置、可执行文件位置、工作目录和用户数据目录是四个概念。只写 Path("config.json"),程序会随启动方式改变行为;把只读内置资源与可编辑外部配置分开,才能解释路径。
构建还必须可复现。依赖版本与哈希、Python 版本、PyInstaller 参数和资源清单都进入版本管理,构建前先跑上一篇测试。记忆点是:打包冻结的是依赖,不是运行现场。客户路径、权限、区域格式和安全软件仍需在目标环境验证。
五、诊断包是交付物的一部分
顶层入口把错误类别、程序版本、任务键和日志路径写入 UTF-8 文件,窗口即使关闭,客户也能找到证据。诊断包默认只收集版本、配置摘要、事件日志与系统架构,不收集凭据和业务原文。若杀毒软件拦截,应提供文件摘要、签名信息和替代的目录版构建,不能要求客户关闭防护。
验收在干净虚拟机上完成:解压、编辑示例配置、运行固定复现包、核对报告、制造一次错误并找到日志。还要验证中文路径、只读目录和非管理员账户。下一篇将读取构建摘要、测试结果和使用说明,用机器可检查的清单完成最终交接。
程序升级也要提前设计。可执行文件与外部配置分别带版本,启动时先验证配置模式;新程序若无法读取旧配置,应给出迁移说明而不是覆盖。用户数据、日志和配置不要塞进程序安装目录,尤其在受保护目录下普通账户没有写权限。升级只替换二进制,回滚时旧版本仍能找到兼容配置和状态数据库。
构建产物发布前计算 SHA-256,并把摘要、构建时间、源代码提交号和依赖锁摘要写进清单。摘要不能证明软件天然安全,却能证明客户运行的文件与验收文件一致。若需要签名,应使用受控证书和时间戳服务,私钥绝不能进入仓库或普通构建日志。交付的不是一个神秘 EXE,而是一条可验证来源与可诊断运行路径。
使用说明还应给出正常退出码、常见错误码和日志目录的截图式路径示例。客户无需理解 Python,也能把准确的任务键与错误码反馈回来;维护者再用上一篇的复现包定位对应分支,远程沟通就不必依赖含糊的"闪退"描述。
📌 本文从路径、可复现构建和本地诊断三个方面补齐了 Windows 可执行文件交付的关键边界。
💬 你打包 Python 工具时,最常遇到的是依赖缺失、资源路径、误报还是日志难找?
👉 关注《Python 自动化接单实战》,最后一篇将把需求确认、报价、验收和交接整理成完整清单。