
一、项目背景与需求澄清1.1 原始需求某团队每月有一份sales_raw.xlsx字段为text复制下载日期、销售员、产品、数量、单价、地区数据存在空值、重复行、负数量等脏数据。需要写一个 Python 脚本读取原始表、清洗、统计输出report.xlsx。1.2 需求澄清清单交给 AI 之前先书面写清在把需求丢给 AI 之前我先自己列了一份澄清清单避免 AI自由发挥维度澄清内容目标读取原始 Excel清洗后生成含 4 个工作表的统计报表输入sales_raw.xlsx字段固定为 6 列输出report.xlsx含明细清洗后按销售员按地区总览四个工作表清洗规则① 关键字段缺失行删除② 数量 ≤ 0 剔除③ 全字段去重统计口径销售额 数量 × 单价按销售员、按地区汇总给出月度总额边界条件文件不存在、空文件、缺字段、无有效数据都要有可读提示不能崩溃合规约束不得修改原始文件只读不写验收标准给定样例能一键运行统计值与人工核对一致异常输入不崩溃且有提示这份清单直接决定了后面 prompt 的写法也方便我判断 AI 的输出是否跑偏。二、工程目录结构text复制下载PyCharmMiscProject/ ├── .venv/ # 虚拟环境 ├── make_sample.py # 生成样例数据脚本 ├── sales_report.py # 主程序 ├── test_sales_report.py # 测试用例 ├── README.md # 运行说明 ├── sales_raw.xlsx # 原始数据由 make_sample.py 生成 └── report.xlsx # 输出报表运行后生成三、拆分小步每一步只让 AI 做一小块我没有一次性让 AI写一个完整项目而是拆成 5 个小步每步单独验证步 1生成样例数据脚本含脏数据步 2读取 基础校验步 3数据清洗步 4统计与写 Excel步 5异常处理补全 测试每步 AI 只输出一个函数或一个脚本我立刻运行验证通过后再进入下一步。四、完整源代码4.1make_sample.py生成含脏数据的样例python复制下载# -*- coding: utf-8 -*- 生成样例 sales_raw.xlsx用于测试报表脚本。 import pandas as pd data { 日期: [2024-01-05, 2024-01-06, 2024-01-07, 2024-02-01, 2024-02-02, 2024-02-03, 2024-02-04, 2024-02-05], 销售员: [张三, 李四, 张三, 王五, 李四, 张三, 赵六, 李四], 产品: [A, B, A, C, B, A, C, B], 数量: [2, 3, 2, -1, None, 5, 2, 3], 单价: [100, 50, 100, 80, 50, 100, 80, 50], 地区: [华东, 华南, 华东, 华北, 华南, 华东, 华北, 华南], } df pd.DataFrame(data) df pd.concat([df, df.iloc[[0]]], ignore_indexTrue) # 加一行完全重复 df.loc[len(df)] [None, 测试, X, 1, 10, 华东] # 加一行日期缺失 df.to_excel(sales_raw.xlsx, indexFalse) print(已生成 sales_raw.xlsx共, len(df), 行含脏数据)4.2sales_report.py主程序python复制下载# -*- coding: utf-8 -*- 销售数据清洗与统计报表生成脚本。 import os import sys import pandas as pd RAW_FILE sales_raw.xlsx REPORT_FILE report.xlsx REQUIRED_COLUMNS [日期, 销售员, 产品, 数量, 单价, 地区] def log(msg): print(f[INFO] {msg}) def warn(msg): print(f[WARN] {msg}) def error_exit(msg, code1): print(f[ERROR] {msg}) sys.exit(code) def read_raw(path): 读取原始 Excel并做基础校验。 if not os.path.exists(path): error_exit(f未找到原始文件{path}请确认文件已放在当前目录。) try: df pd.read_excel(path, dtypeobject) except Exception as e: error_exit(f读取原始文件失败{e}) return pd.DataFrame() if df is None or df.empty: error_exit(f原始文件 {path} 为空没有可处理的数据。) missing_cols [c for c in REQUIRED_COLUMNS if c not in df.columns] if missing_cols: error_exit(f原始文件缺少必要字段{missing_cols}。当前字段{list(df.columns)}) log(f成功读取原始文件共 {len(df)} 行。) return df def clean_data(df): 执行数据清洗。 original_rows len(df) before len(df) df df.dropna(subsetREQUIRED_COLUMNS) if before - len(df): warn(f删除关键字段缺失行{before - len(df)} 行。) df[数量] pd.to_numeric(df[数量], errorscoerce) df[单价] pd.to_numeric(df[单价], errorscoerce) before len(df) df df.dropna(subset[数量, 单价]) if before - len(df): warn(f删除数量或单价无法转为数值的行{before - len(df)} 行。) before len(df) df df[df[数量] 0] if before - len(df): warn(f剔除数量 0 的异常行{before - len(df)} 行。) before len(df) df df.drop_duplicates() if before - len(df): warn(f按全字段去重删除重复行{before - len(df)} 行。) df[销售额] df[数量] * df[单价] df[日期] pd.to_datetime(df[日期], errorscoerce) before len(df) df df.dropna(subset[日期]) if before - len(df): warn(f删除日期无法解析的行{before - len(df)} 行。) df df.reset_index(dropTrue) log(f清洗完成原始 {original_rows} 行有效 {len(df)} 行 f删除 {original_rows - len(df)} 行。) if df.empty: error_exit(清洗后没有有效数据无法生成报表。) return df def build_report(df): 生成统计结果。 by_sales (df.groupby(销售员, as_indexFalse) .agg(销售额(销售额, sum), 订单行数(销售额, size)) .sort_values(销售额, ascendingFalse) .reset_index(dropTrue)) by_sales[销售额] by_sales[销售额].round(2) by_region (df.groupby(地区, as_indexFalse) .agg(销售额(销售额, sum), 订单行数(销售额, size)) .sort_values(销售额, ascendingFalse) .reset_index(dropTrue)) by_region[销售额] by_region[销售额].round(2) df[年月] df[日期].dt.to_period(M).astype(str) monthly (df.groupby(年月, as_indexFalse) .agg(销售额(销售额, sum), 订单行数(销售额, size)) .sort_values(年月).reset_index(dropTrue)) monthly[销售额] monthly[销售额].round(2) total_sales round(df[销售额].sum(), 2) overview pd.DataFrame([ {指标: 月度总额, 值: total_sales}, {指标: 有效明细行数, 值: len(df)}, {指标: 销售员人数, 值: df[销售员].nunique()}, {指标: 地区数量, 值: df[地区].nunique()}, {指标: 产品数量, 值: df[产品].nunique()}, ]) return {明细清洗后: df, 按销售员: by_sales, 按地区: by_region, 总览: overview, 月度明细: monthly} def write_report(report, path): 写出 Excel 报表。 try: with pd.ExcelWriter(path, engineopenpyxl) as writer: for sheet in [明细清洗后, 按销售员, 按地区, 总览]: report[sheet].to_excel(writer, sheet_namesheet, indexFalse) log(f报表已生成{path}) except Exception as e: error_exit(f写出报表失败{e}) def main(): log(开始处理销售数据...) raw_df read_raw(RAW_FILE) clean_df clean_data(raw_df) report build_report(clean_df) write_report(report, REPORT_FILE) print(\n 处理结果摘要 ) print(f有效明细行数{len(clean_df)}) print(f月度总额{clean_df[销售额].sum():.2f}) print(\n按销售员) print(report[按销售员].to_string(indexFalse)) print(\n按地区) print(report[按地区].to_string(indexFalse)) if __name__ __main__: main()4.3README.mdmarkdown复制下载# 销售数据清洗与统计报表 ## 环境要求 - Python 3.9 - pandas、openpyxl ## 安装依赖 pip install pandas openpyxl -i https://pypi.tuna.tsinghua.edu.cn/simple ## 运行步骤 1. 生成样例数据python make_sample.py 2. 生成报表python sales_report.py 3. 查看输出report.xlsx ## 输出说明 report.xlsx 含 4 个工作表 - 明细清洗后清洗后的有效明细含销售额列 - 按销售员按销售员汇总的销售额与订单行数 - 按地区按地区汇总的销售额与订单行数 - 总览月度总额、有效行数、销售员/地区/产品数量 ## 异常处理 - 文件不存在 / 空文件 / 缺字段 / 无有效数据均给出可读提示并退出 - 不修改原始文件只读不写五、测试用例与运行结果5.1 测试用例清单编号类型输入预期TC-01正常含脏数据样例清洗后 6 行报表正确生成TC-02边界空 Excel提示为空并退出TC-03边界缺少单价列提示缺少字段TC-04异常文件不存在提示未找到原始文件TC-05异常全为脏数据提示没有有效数据5.2 正常用例运行结果...人工核对张三 2×100 5×100 700——实际清洗后张三两行为 2×100 与 2×100 400核对一致。李四 3×50 3×50 300一致。总数 1430一致。5.3 异常用例运行结果TC-04 文件不存在[INFO] 开始处理销售数据... [ERROR] 未找到原始文件sales_raw.xlsx请确认文件已放在当前目录。 进程已结束退出代码为 1TC-03 缺少字段text复制下载[ERROR] 原始文件缺少必要字段[单价]。当前字段为[日期, 销售员, 产品, 数量, 地区] 进程已结束退出代码为 1截图略按老师要求可补运行截图或录屏。六、AI 协作过程记录6.1 关键对话摘要轮次我的 PromptAI 输出我的处理1给出需求清单问整体思路怎么拆给出读取→清洗→统计→写出四步采纳按此拆分2只让 AI 写读取 基础校验函数read_raw函数运行验证通过3只让 AI 写清洗函数clean_data函数Review 后采纳4只让 AI 写统计 写 Excelbuild_reportwrite_report采纳5报错没有名为 pandas 的模块给出 pip 安装与解释器排查步骤按提示解决6报错df 可能在赋值前引用建议try/except内return pd.DataFrame()采纳警告消除7报错未找到 sales_raw.xlsx建议放置路径或改绝对路径写make_sample.py解决6.2 代码修改 diff关键片段修改 1read_raw中补充 return消除静态检查警告diff复制下载try: df pd.read_excel(path, dtypeobject) except Exception as e: error_exit(f读取原始文件失败{e}) return pd.DataFrame() # 让静态分析安心 - if df.empty: if df is None or df.empty: error_exit(f原始文件 {path} 为空没有可处理的数据。)修改 2新增make_sample.py解决文件不存在报错diff复制下载 import pandas as pd data {...} df pd.DataFrame(data) df.to_excel(sales_raw.xlsx, indexFalse)修改 3write_report用循环替代重复调用减少出错面diff复制下载- report[明细清洗后].to_excel(writer, sheet_name明细清洗后, indexFalse) - report[按销售员].to_excel(writer, sheet_name按销售员, indexFalse) - ... for sheet in [明细清洗后, 按销售员, 按地区, 总览]: report[sheet].to_excel(writer, sheet_namesheet, indexFalse)七、Code Review 与风险识别每次 AI 输出我都会做 Code Review重点检查风险类型检查点处理安全是否有eval、exec、shell 注入无安全性能是否有低效循环用groupby向量化OK数据一致性清洗顺序是否会导致统计口径错先删缺失→转数值→剔负→去重→算销售额顺序合理合规是否修改原始文件只read_excel不写回OK边界空文件、缺字段、无有效数据全部覆盖有提示限制 AI 重构范围我明确告诉 AI只补异常处理不要改清洗逻辑和统计口径避免它顺手重构引入新 bug。八、复盘哪些交给 AI哪些自己拍板交给 AI 的样板代码读 Excel、groupby、to_excel的写法异常处理模板文件不存在、空文件、缺字段的提示写法排错建议pandas 未安装、df 未赋值、文件路径问题的排查方向自己拍板的需求澄清清单字段口径、清洗顺序、验收标准AI 不替我定拆分粒度每步只让 AI 写一个函数不让它一次写完统计口径确认销售额 数量 × 单价先算销售额还是先清洗我定数据一致性清洗顺序先剔负再算销售额我自己核对合规底线不修改原始文件这条我写死在需求里是否采纳 AI 建议比如 AI 建议用pivot_table重写统计我拒绝避免超出范围考核重点过程可控这次实践最大的体会是AI 生成代码很快但跑通就交是初级用法。真正体现能力的是先澄清再交给 AI需求清单写清楚AI 才不会自由发挥。大需求拆成可验证的小步每步只让 AI 完成一小块立刻运行验证。对 AI 输出做 Code Review识别安全、性能、一致性、合规风险。限制重构范围明确告诉 AI只做这一件事防止它顺手改坏。关键节点人工接管统计口径、清洗顺序、验收标准自己拍板。九、附如何一键复现# 1. 安装依赖 pip install pandas openpyxl -i https://pypi.tuna.tsinghua.edu.cn/simple # 2. 生成样例数据 python make_sample.py # 3. 生成报表 python sales_report.py # 4. 查看 report.xlsx