客户说“整理一下 Excel”,背后往往同时包含改列名、去空格、金额转换、重复行处理和异常留痕。真正可交付的脚本不能把坏数据悄悄丢掉,也不能让一处格式变化拖垮整批文件。
这一篇延续前两篇的配置驱动思路:先把输入统一成行记录,再让规则函数返回“结果或错误”,最后分别输出干净数据与异常报告。示例使用标准库 CSV,接入 Excel 时只需替换读写适配层。
一、先定义不会含糊的验收规则
假设订单至少需要order_id、amount和customer。金额必须非负,订单号不能为空;同一个订单号重复出现时,保留第一条并把其余记录写入异常文件。
fromdecimalimportDecimal,InvalidOperationdefclean(row):order_id=row.get("order_id","").strip()customer=row.get("customer","").strip()ifnotorder_id:raiseValueError("missing order_id")try:amount=Decimal(row.get("amount","").replace(",","").strip())exceptInvalidOperationasexc:raiseValueError("invalid amount")fromexcifamount<0:raiseValueError("negative amount")return{"order_id":order_id,"customer":customer,"amount":str(amount)}规则函数不负责打印,也不直接写文件,因此可以独立测试。客户修改金额约束时,只改这一层。
二、让每条失败记录都能回到原始位置
importcsv seen,accepted,rejected=set(),[],[]withopen("orders.csv",encoding="utf-8-sig",newline="")assource:forline_no,rowinenumerate(csv.DictReader(source),start=2):try:item=clean(row)ifitem["order_id"]inseen:raiseValueError("duplicate order_id")seen.add(item["order_id"])accepted.append(item)exceptValueErrorasexc:rejected.append({"line":line_no,"reason":str(exc),**row})print(f"accepted={len(accepted)}rejected={len(rejected)}")输出示例:
accepted=248 rejected=7交付时还应把accepted和rejected分别写入文件,并在异常报告中保留源文件名、行号和原因。这样客户可以修正 7 条数据后重跑,而不是重新核对 255 行。
三、批量目录要有明确停止条件
先用 2—3 个脱敏文件验证列名、编码和日期格式,再扩展到整个目录。若必填列缺失,应停止当前文件;若只是单行金额错误,则隔离该行并继续。规则不明确时先补样例,不要凭经验猜客户意图。
📌 本文把表格清洗拆成规则函数、正常输出和异常报告,让批量处理既能继续执行,也能逐条追溯。
💬 你的 Excel 清洗任务里,最容易反复变化的是列名、日期、金额还是去重规则?
👉 关注《Python 自动化接单实战》,下一篇继续拆解公开网页文本抓取器的范围控制、规则检查与结构化输出。
参考来源
- Dev.to|Context Is King
- Hacker News|Introduction to Data-Oriented Design