第四章的程序已经能读取一份 JSON,统计订单并按条件查询。现在,电商运营同事每天会导出多份订单文件,希望 IT 工程师把它升级成能够反复使用的批量处理工具。
本章围绕一次完整升级展开:理解已有程序、明确业务规则、分步实现、验证结果,最后把工具交给同事使用。
5.1 场景变化:一份文件变成一批文件
每天手动替换"订单数据.json"并重复运行,容易漏文件,也很难发现文件之间重复导出的订单。新需求是指定一个目录,一次处理其中的订单文件,导出筛选结果,并单独列出需要人工确认的问题。
| 能力 | 第四章 | 本章升级 |
|---|---|---|
| 输入 | 默认读取一份 JSON | 保留默认方式,增加目录批量读取 |
| 数据处理 | 输入已经去重 | 跨文件去重,隔离冲突和非法记录 |
| 查询 | 商品与状态组合筛选 | 保留原功能,基于有效订单查询 |
| 输出 | 终端显示 | 终端摘要、结果 CSV、问题 CSV、摘要 JSON |
| 使用方式 | 自己在项目目录运行 | 同事按说明指定目录,识别结果和异常 |
模型可以完成代码,但"相同订单出现两种状态时采用哪一条"需要业务规则。 先明确规则,才能判断程序是否满足需求。
本例处理同一批订单的重叠导出,不是按时间回放订单状态变化。输入没有可靠的更新时间,因此不按文件名或读取顺序挑选"最新状态"。
5.2 接手程序:先了解已有行为
复制第四章已经生成的项目,保留原始版本。将第五章配套资料中的"批量输入""边界输入"和"升级需求.md"复制到项目根目录。
订单统计工具/
├── main.py
├── 订单数据.json
├── 需求说明.md
├── 升级需求.md
├── README.md
├── 批量输入/
│ ├── 01-首批导出.json
│ └── 02-补充导出.json
└── 边界输入/
├── 空数组/
└── 格式损坏/
先让 Codex 了解代码:
请读取当前 main.py、需求说明.md 和升级需求.md。
先说明现有输入路径、统计与筛选逻辑,以及适合扩展的位置。
运行原有四种查询命令,记录结果作为回归依据。
暂时不要修改代码;若当前行为与第四章需求不一致,先说明差异。
| 命令 | 匹配数 | 全量统计 |
|---|---|---|
| py main.py | 8 | 已支付 6、待支付 1、已取消 1 |
| py main.py --product "机械键盘" | 4 | 同上 |
| py main.py --product "机械键盘" --status "已支付" | 3 | 同上 |
| py main.py --product "蓝牙耳机" --status "已取消" | 0 | 同上 |
如果第四章已增加各商品已支付订单数,两类商品应各为 3。升级后仍需保留。
5.3 明确规则:重复、冲突与缺失如何处理
配套批量数据共 16 条原始记录,包含重叠导出、同编号不同状态、必填字段缺失和渠道缺失。规模保持可逐条核对,重点在规则和交付流程。
本例只接受 id、product、status、channel 四个字段。前三项为非空字符串,status 只能是"已支付、待支付、已取消"。channel 可以缺失或为空,统一为"未填写";其他类型视为非法。出现额外字段也视为非法,避免静默丢失业务信息。
处理顺序:
- 校验记录,非法记录写入问题清单,不参与后续去重和统计。
- 将缺失或空渠道规范为"未填写";其余字符串不自动改写。
- 按规范后的四个业务字段去除完全相同的重复记录,保留来源。
- 同一 id 如果仍有多个不同版本,所有版本进入冲突清单,全部排除出有效订单。
- 对有效订单进行全量统计,再应用查询条件。
| 情况 | 示例 | 处理 |
|---|---|---|
| 完全重复 | O003 在两份文件中完全一致 | 只计一次,报告重复来源 |
| 状态冲突 | O005 同时出现待支付与已支付 | 两个版本均隔离 |
| 必填缺失 | O012 没有 product | 非法记录,排除 |
| 渠道缺失 | O010 没有 channel | 保留,显示未填写 |
| 无匹配 | 查询不存在的商品 | 合法空结果,结果 CSV 只有表头 |
"保留最后一条"会让结果依赖文件顺序;"出现已支付就计入"也是额外业务假设。本例统一隔离冲突,不推断真实状态。
本例没有金额、支付流水和发货记录,也不接受"已发货"状态,不能据此判断到账金额或履约情况。第三章的多表交易核对需要另一套业务规则。
5.4 分两步完成升级
第一步:批量读取与清洗
请按升级需求.md 增加 --input-dir 参数,保留默认输入和原有筛选方式。
指定目录时只读取第一层 .json 文件,按文件名排序。
显式相对路径按终端当前目录解释。
使用 Python 标准库,将读取、清洗、统计筛选分开组织,避免无关重写。
先完成批量读取、清洗和终端摘要,暂时不做导出。
摘要分别报告原始记录、非法记录、完全重复的额外记录、
冲突编号、冲突版本、有效订单、各状态数量及匹配数。
问题保留源文件名与从 1 开始的数组记录序号。
实际运行批量输入,报告实现内容、实测结果及未完成项。
记录序号是 JSON 数组中的位置,不是文本行号,方便定位原始记录。
py main.py --input-dir "批量输入"
py main.py --input-dir "批量输入" --product "机械键盘" --status "已支付"
| 指标 | 预期 |
|---|---|
| 原始记录 | 16 |
| 非法记录 | 1 |
| 完全重复的额外记录 | 2 |
| 冲突编号 / 冲突版本 | 1 / 2 |
| 有效订单 | 11 |
| 有效订单状态 | 已支付 8、待支付 2、已取消 1 |
| 机械键盘且已支付 | 4 |
16 = 1 条非法 + 2 条重复额外记录 + 2 条冲突版本 + 11 条有效订单。冲突编号是分组数,不能再加进等式。
筛选只改变匹配列表,不改变有效订单的全量统计。
第二步:导出可核对的结果
请增加 --output-dir 参数,将结果写入全新目录。
输出筛选结果.csv、问题清单.csv、处理摘要.json。
CSV 使用 utf-8-sig,标准库 csv 配合 newline=""。
筛选结果表头:编号、商品、状态、来源渠道,按编号排序。
问题清单表头:类型、订单编号、源文件、记录序号、说明。
重复只报告额外行,冲突报告所有版本,非法记录逐条报告;
问题清单不受商品和状态筛选影响。
摘要包含输入文件、清洗指标、全量状态统计、筛选条件、
匹配数及是否存在待处理数据问题。
未传 --output-dir 不创建文件;已有目标目录一律拒绝覆盖。
先完成输入读取与格式校验,再创建输出目录。
写入失败必须报告失败,说明可能留下不完整目录。
退出码遵循升级需求:0 正常,1 完成但有冲突或非法记录,2 执行失败。
更新 README,运行导出并读取三个实际文件核对内容。
py main.py --input-dir "批量输入" --product "机械键盘" --status "已支付" --output-dir "输出/键盘核对-01"
$LASTEXITCODE
结果 CSV 应为 O003、O006、O008、O011 四条。问题清单共 5 行:重复 2、冲突 2、非法 1。渠道缺失是允许的数据情况,不计入问题清单。
退出码应为 1,表示处理完成,但 O005 冲突和 O012 非法记录需要业务确认。文件已生成与业务数据全部合格,是两件事。
CSV 可以在 Excel 或 WPS 中打开,但不包含工作簿样式、多工作表和图表。
5.5 验收:检查结果,也检查原功能
请按配套资料的验收清单检查程序。
先列出命令、预期和输出目录,再实际执行。
每个场景使用独立输出目录,重复路径检查除外。
核对退出码、摘要与实际文件,不能只检查"运行没报错"。
记录实测结果,未执行的项目明确标记。
最后重新运行第四章四条命令,确认原功能保留。
| 场景 | 预期 |
|---|---|
| 批量处理 | 原始 16,有效 11 |
| 组合筛选并导出 | 键盘已支付 4 条,全量已支付仍为 8 |
| 无匹配并导出 | 结果 CSV 仅表头,问题仍有 5 行,退出码 1 |
| 重复使用输出目录 | 拒绝覆盖,退出码 2,原文件不变 |
| 边界输入/空数组 | 全部数量 0,退出码 0 |
| 不存在的目录或没有 JSON 的目录 | 报错,退出码 2,不创建输出 |
| 边界输入/格式损坏 | 报告文件名与格式问题,退出码 2,不创建输出 |
| 默认单文件模式 | 第四章四种查询结果保持不变 |
完整命令见验收清单。边界输入用于确认输入契约,不需要修改程序来制造缺陷。
可让 Codex 把跨文件去重、冲突全部隔离、筛选不改变全量统计和拒绝覆盖整理成自动检查。预期来自业务规则与可核对的数据,而不是照抄当前程序的输出。
如果结果不符,再提供完整命令、实际结果和预期:
运行 py main.py --input-dir "批量输入" 后,O005 仍在有效订单中。
需求要求同编号不同版本全部隔离,预期有效订单为 11 条。
请检查去重和冲突判断的先后顺序,说明原因后修复。
保留输入数据,重新验证默认模式和批量模式。
这只是出现差异时的反馈方式;实际符合需求时,直接继续交付。
5.6 保存版本并审查修改
升级前保留可恢复版本,完成批量清洗后记录一次,完成导出与验收后再记录一次。小项目可以用不同目录保存副本;使用 Git 时,提交说明可写"增加批量订单清洗""增加导出与交付说明"。
请列出本次修改文件,说明各项变更对应哪条需求。
检查是否改动输入,是否增加无关依赖。
列出适合纳入 Git 的源码、需求、教学样例和检查脚本,
排除凭据、缓存和生成的结果文件。
先展示清单,等我确认后再创建本地提交。
本地提交是在本机记录版本,不等于上传远程仓库。需要比较旧版时,在另一个目录运行并保留当前修改。
审查聚焦具体风险:
请审查本次升级,重点检查跨文件去重、冲突隔离、路径处理、
退出码和拒绝覆盖。只报告有代码依据的问题及触发条件。
区分代码审查与实际运行结果,不把未运行的检查写成通过。
审查查看实现是否存在遗漏,运行检查确认给定输入下的实际表现。两者互相补充。
5.7 交付:让同事按说明完成处理
请按当前真实实现更新 README.md。
说明 Python 环境、文件用途、默认模式、批量模式、筛选和导出命令。
默认输入相对于脚本目录;显式输入输出相对路径按终端当前目录解释。
写清清洗顺序、输出字段、退出码、实际检查和已知限制。
提供"准备输入→运行→查看结果→处理异常"的操作步骤。
不要写入未实现功能,不把教学样例描述成真实业务数据。
交付包包含源码、原始需求、升级需求、README、教学输入和检查脚本。复制到新文件夹后,按说明重跑默认查询与批量导出,确认没有依赖原目录中的文件。
同事准备好 Python、放入约定格式的数据,再执行命令即可使用;不需要了解去重实现,也不需要模型 API Key。开发时 Codex 调用模型,与生成后的工具如何运行,是两个环节。
O005 的真实状态需要业务确认;O012 应由数据提供方补齐商品信息后重新导出。工具提供问题及来源,不自动补写未知事实。
下一章介绍 MCP,进一步理解 Agent 如何调用已有工具与业务服务。