ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Vibe Coding 考核实录:我把 AI 当结对程序员,做完了一个数据清洗脚本和一个记账接口

Vibe Coding 考核实录:我把 AI 当结对程序员,做完了一个数据清洗脚本和一个记账接口 课堂上参加了一场 Python 方向的 Vibe CodingAI 辅助编程考核限时 60 分钟。说实话进考场之前我是有点心虚的。我的 Python 底子很一般pandas 的 API 每次都要现查FastAPI 也只会照着官方文档改改。但这场考核的规则挺特别允许你随便用 AICopilot、Cursor、通义灵码都行唯一的要求是必须留下对话记录和代码修改轨迹。考完我最大的感受是这场考试从头到尾没考我会不会写代码考的是我会不会提需求。今天把整个过程复盘一遍也算给自己留个存档。一、先搞清楚考核到底要什么题目本身不复杂两道题考题一Excel 报表生成脚本40 分背景是某团队每个月都有一份sales_raw.xlsx字段是日期、销售员、产品、数量、单价、地区里面混着空值、重复行、负数量这几种脏数据。要做的事是读原始表 → 清洗 → 按销售员和地区汇总销售额 → 输出report.xlsx里面要包含「明细清洗后」「按销售员」「按地区」「总览」四个工作表。考题二FastAPI 记账接口实现一个简易记账服务数据内存存就行。三个接口POST /records新增流水要校验金额 0、类型只能是收入/支出、日期格式合法GET /records支持按类型、分类、日期区间筛选还要分页GET /summary返回指定日期区间的收入合计、支出合计和结余要交的东西有 5 样需求澄清清单、可运行的工程、测试用例和运行截图、AI 协作过程记录含对话摘要和 diff、一段文字复盘。评分是五个维度——结果、过程、验证、风险、复盘。题目里有一句话我印象特别深仅让 AI 生成、跑通就交按初级用法处理过程分上限受限。翻译过来就是你把需求一丢AI 把代码吐出来你python xxx.py跑通了就交卷——这种用法直接按最低档算。它要的是过程可控。二、我做的第一件事不写代码先写文档我花了大概 5 分钟一行代码没敲先在docs/requirements.md里把需求拆开写清楚了。## 1. 目标 读取 data/sales_raw.xlsx清洗脏数据统计销售额输出 report.xlsx。 ## 2. 输入与输出 - 输入data/sales_raw.xlsx存在空值、重复行、负数量 - 输出report.xlsx含4个Sheet明细清洗后、按销售员、按地区、总览 ## 3. 边界与异常处理 - 关键字段日期、销售员、数量、单价、地区缺失的行直接删除。 - 数量 0 的异常行直接剔除。 - 全字段去重完全相同的行只保留一条。 - 空文件、缺列、无有效数据不得崩溃需在控制台给出可读的中文报错提示。 - 约束绝对不能修改或覆盖原始文件 sales_raw.xlsx。 ## 4. 验收标准 - 一键运行python src/excel_report.py能生成 report.xlsx。 - 统计数值需与人工核对一致。 - 故意制造空文件或缺列脚本能优雅报错不抛出长篇底层 Traceback。这 5 分钟花得特别值。因为后面我发现AI 能帮你写dropna()但它永远不会替你决定关键字段到底包含哪几个——产品字段缺失要不要删数量为负是删还是取绝对值这些都得我自己拍板。你不先定AI 就会按它自己的理解来最后出来的结果跟你的预期对不上你还得回头重来。我给自己定了几条规矩写在需求文档里产品字段不算关键字段允许为空不然会误删数据数量 ≤ 0 直接剔除不取绝对值负数量基本可以判定是录入错误异常一律给中文提示不要把 Traceback 甩给用户看先定规矩再让 AI 干活。三、工程结构目录没有搞得很花哨能跑通、能一眼看懂就行PyCharmMiscProject/ ├── data/ │ └── sales_raw.xlsx # 原始测试数据含有空值、重复行、负数量 ├── docs/ │ ├── requirements.md # 需求澄清清单 │ └── ai_log.md # AI协作过程记录与Diff ├── src/ │ ├── excel_report.py # 考题一Excel报表生成脚本 │ └── fastapi_app.py # 考题二FastAPI记账接口 ├── tests/ │ ├── test_excel.py # 考题一测试用例1正常3异常 │ └── test_api.py # 考题二测试用例6个核心用例 ├── pytest.ini # 解决项目根路径导入问题的配置 ├── requirements.txt # 项目依赖清单 └── README.md # 运行说明与复盘四、考题一Excel 清洗脚本以及三个真实的坑4.1 核心逻辑清洗其实就三行# 5. 数据清洗 # 5.1 删除关键字段缺失的行产品不作为关键字段允许为空 df_clean df.dropna(subsetrequired_cols).copy() # 5.2 剔除数量0的异常行 df_clean df_clean[df_clean[数量] 0] # 5.3 按全字段去重 df_clean df_clean.drop_duplicates()统计部分用groupby最后用ExcelWriter一次写四个 Sheet。4.2 坑一这个 .xlsx 根本就不是 Excel 文件第一个坑来得很快。我用pd.read_excel()读sales_raw.xlsx直接报错File is not a zip file当时我第一反应是文件坏了。后来才反应过来——这个xlsx很可能是别人用文本编辑器直接改后缀名造出来的假文件本质是纯文本压根不是 zip 包。我的处理方式没有去网上找一堆修复工具而是自己写了个make_data.py用 pandas 把数据重新写一遍强制输出成真正的 xlsximport pandas as pd data { 日期: [2023-10-01, 2023-10-01, 2023-10-02, 2023-10-03, 2023-10-04, 2023-10-05, 2023-10-06], 销售员: [张三, 张三, 李四, None, 王五, 赵六, 钱七], 产品: [A, A, B, C, D, E, F], 数量: [10, 10, -5, 2, 5, 3, 8], 单价: [100, 100, 50, 20, 200, 50, 30], 地区: [华东, 华东, 华南, 华北, 华东, None, 华南] } df pd.DataFrame(data) # 强制写出真正的 xlsx 文件 df.to_excel(data/sales_raw.xlsx, indexFalse, engineopenpyxl) print(【成功】真正的 sales_raw.xlsx 文件已生成)同时在读取的地方显式指定引擎免得 pandas 猜来猜去df pd.read_excel(input_path, engineopenpyxl)顺便说一句那份测试数据是我故意造脏的第 2 行和第 1 行完全重复、李四那行数量是 -5、赵六那条销售员为空、还有一条地区为空。7 行数据洗干净之后只剩 3 行——这才是能验证逻辑的样本。4.3 坑二差点让 AI 把原始文件改了这是我全场最惊险的一个点。AI 给我的第一版代码里有这么一句df[销售额] df[数量] * df[单价]看着没毛病对吧但它是在df这个原始 DataFrame 上直接加列。而 pandas 的dropna()、df[mask]这些操作很多时候返回的是视图不是副本你在上面加列有可能连底层数据一起动到。考题里写死了绝对不能修改或覆盖原始文件这属于数据一致性的红线。所以我把这一句改成了先.copy()df_clean df.dropna(subsetrequired_cols).copy()一行.copy()换一个不会污染源数据。这种地方 AI 不会主动提醒你得你自己盯着。4.4 坑三异常处理不是套一层 try 就完事我列的异常场景有四个文件不存在、文件读取失败、文件为空、缺关键字段还有清洗后无有效数据。AI 一开始只给了一个try-except把read_excel包起来。但真跑起来你会发现文件不存在和文件为空是两码事得分开报# 1. 异常处理文件不存在 if not os.path.exists(input_path): print(f【错误】找不到输入文件{input_path}请检查路径) return try: df pd.read_excel(input_path, engineopenpyxl) except Exception as e: print(f【错误】读取Excel失败可能是文件损坏或格式不对。详细信息{e}) return # 3. 异常处理空文件 if df.empty: print(【错误】输入文件为空没有数据可以处理) return # 4. 检查关键字段是否存在 required_cols [日期, 销售员, 数量, 单价, 地区] missing_cols [col for col in required_cols if col not in df.columns] if missing_cols: print(f【错误】文件缺少关键字段{missing_cols}请检查表头) return # 6. 异常处理清洗后无有效数据 if df_clean.empty: print(【警告】清洗后无有效数据无法生成统计报表) return注意最后那个df_clean.empty——这个判断是 AI 一开始没给的是我自己补上去的。想一下如果一份表所有行的数量都是负数清洗完就是空表你再去groupby出来的报表全是空的用户拿到手一脸懵。这种清洗后为空的情况是最容易被漏掉的。4.5 结果验证跑python src/excel_report.py终端输出开始执行报表生成任务... 【成功】报表已生成report.xlsx 【统计结果】月度总额为2240打开report.xlsx四个 Sheet 都对得上明细清洗后——7 行脏数据只剩 3 行张三那条重复的被去掉了李四的负数量被剔了销售员/地区为空的两条也没了按地区——华东 2000张三 1000 王五 1000华南 240按销售员——张三 1000、王五 1000、钱七 240总览——月度总额 2240跟人工心算的结果一致五、考题二FastAPI 记账接口5.1 校验交给 Pydantic不要自己写 if这一题我觉得最省心的一点是把参数校验整个交给了 Pydanticclass RecordCreate(BaseModel): amount: float Field(..., gt0, description金额必须大于0) type: Literal[收入, 支出] category: str Field(..., min_length1) date: date class RecordResponse(RecordCreate): id: intgt0管金额Literal管类型枚举date管日期格式。错一个字段框架自动返回 422我一行 if-else 都不用写。这里有个小细节值得说422 和 500 的区别。如果我把校验逻辑自己写在函数里然后raise HTTPException(500)那前端拿到的就是服务器挂了。而 422 是你传的参数我不认语义完全不同。这个点我是专门人工 review 过的不是 AI 主动提醒的。5.2 并发安全一个 Lock 解决问题题目说并发写入不产生数据错误能说明如何保证即可。AI 给了两个方案threading.Lock或者换成数据库事务。我选了前者。原因很实在——数据本来就存内存为了并发安全上 SQLite 属于给自己加戏而且 60 分钟的时间也不允许。一个锁就够records_db [] db_lock threading.Lock() app.post(/records, response_modelRecordResponse, status_codestatus.HTTP_201_CREATED) def create_record(record: RecordCreate): with db_lock: # 加锁保证并发安全 new_record record.model_dump() new_record[id] len(records_db) 1 records_db.append(new_record) return new_record为什么非加不可因为len(records_db) 1和append()这两步之间不是原子的。两个请求同时进来可能算出同一个 id或者其中一个 append 被另一个覆盖。加锁之后这两个动作变成一个整体问题就没了。这个决定是我自己拍的板并且写进了 README免得日后别人接手看不懂。5.3 兜底全局异常处理器最后再加一层全局兜底任何没被捕获的异常都返回结构化信息而不是一堆 HTML 堆栈app.exception_handler(Exception) async def global_exception_handler(request, exc): return JSONResponse( status_code500, content{message: 服务器内部错误, detail: str(exc)} )六、测试4 个用例 6 个用例全绿题目要求含正常用例与至少 2 个边界/异常用例我两边都写超了。考题一—— 1 个正常 3 个异常文件不存在、空文件、缺关键字段(venv) PS C:\Users\...\PyCharmMiscProject pytest tests/test_excel.py -v collected 4 items tests/test_excel.py::test_generate_report_success PASSED [ 25%] tests/test_excel.py::test_file_not_found PASSED [ 50%] tests/test_excel.py::test_empty_file PASSED [ 75%] tests/test_excel.py::test_missing_columns PASSED [100%] 4 passed in 0.42s 考题二—— 6 个用例覆盖了金额非法、类型非法、日期格式错误、筛选分页、汇总计算(venv) PS C:\Users\...\PyCharmMiscProject pytest tests/test_api.py -v collected 6 items tests/test_api.py::test_create_record PASSED [ 16%] tests/test_api.py::test_create_record_invalid_amount PASSED [ 33%] tests/test_api.py::test_create_record_invalid_type PASSED [ 50%] tests/test_api.py::test_create_record_invalid_date PASSED [ 66%] tests/test_api.py::test_filter_and_pagination PASSED [ 83%] tests/test_api.py::test_summary PASSED [100%] 6 passed, 1 warning in 0.25s 异常用例的写法很简单但特别有用——你不需要去构造复杂的场景只要断言状态码对就行# 异常用例1金额0 def test_create_record_invalid_amount(): response client.post(/records, json{ amount: -10, type: 收入, category: 工资, date: 2023-10-01 }) assert response.status_code 422 # Pydantic 自动返回 422这里也踩了一个坑ModuleNotFoundError第一遍跑 pytest直接报错ModuleNotFoundError: No module named src原因是从tests/目录去 import 根目录下的src包Python 默认找不到。解决办法是加一个pytest.ini[pytest] pythonpath .两行配置项目在任何环境下都能一键跑通测试。这种坑很典型代码逻辑明明是对的但环境配置不对照样跑不起来而 AI 一般不会主动告诉你这件事。另外那个1 warning是 Starlette 的弃用警告TestClient 的 httpx 后端变了不影响功能知道它是什么就行。七、AI 帮了我什么我又做了什么这部分我觉得是整场考核最值钱的。我把它拆成三层完全交给 AI 的pandas 清洗的样板代码、FastAPI 的路由模板、pytest 的用例骨架。这些东西有固定写法让 AI 写比我翻文档快十倍也避免了我卡在基础语法上浪费时间。我自己拍板的关键字段到底是哪几个我加了产品不算这是需求层面的判断异常必须输出中文提示而不是直接抛异常给用户并发安全选threading.Lock而不是数据库事务人工审查并动手改的我留了几条 diff df_clean df_clean[df_clean[数量] 0] (人工要求 AI 增加剔除负数量的逻辑) if df_clean.empty: print(【警告】清洗后无有效数据) (人工补充的边界处理) - df[销售额] ... df_clean[销售额] df_clean[数量] * df_clean[单价] (人工纠正不能让 AI 在原表上改必须先 .copy()) df pd.read_excel(input_path, engineopenpyxl) (人工排查文件格式报错后补充的引擎参数)这四条 diff 加起来不到五行代码但每一条都是 AI 不会主动替你想到的。我觉得这就是过程分的来源。八、复盘四个我认为真实存在的风险1. 数据一致性风险——AI 生成的groupby代码我逐行看过确认它没有改动原始表只做读取和聚合。report.xlsx里的数字跟人工核对一致这一步不能省。2. 接口合法性风险——Pydantic 的校验逻辑我专门确认了非法参数返回 422 而不是 500。如果这里错了服务端会频繁抛异常用户看到的是系统故障而不是你参数填错了。3. 文件格式风险——File is not a zip file这个报错挺唬人的但根因很简单伪 xlsx。用 Python 重新生成真正的文件即可。这个坑让我意识到AI 给出的代码对输入数据本身有问题这种情况基本是零防御的。4. 测试路径风险——pytest.ini里加pythonpath .。这个纯粹是工程习惯问题跟 AI 无关但如果不解决交上去的工程在别人电脑上跑不起来。九、最后说两句考完我最大的体会是Vibe Coding 不是躺平式编程。AI 把代码生成的速度提上去了但你的审查速度没有同步提上去那多出来的时间其实是在制造技术债。这次考核里真正花我时间的不是写代码而是这四件事想清楚关键字段是什么判断哪些异常场景必须单独处理检查 AI 有没有偷偷改我的原始数据确认状态码、Sheet 名、统计口径跟需求完全对齐需求是你写的边界是你定的结果是你得验的。AI 只是把你从敲键盘里解放出来让你能专心做上面这四件事。对想入门 Python 的朋友我的建议也很简单别怕自己不会写先学会把一件事讲清楚。你能把要什么、不要什么、错了怎么办讲明白AI 就能帮你把代码补上。代码和测试已经整理好了有问题欢迎评论区聊也可以直接抄我的requirements.md模板去用。
返回列表