Python零基础到批量验收
AI数据采购Owner实战课 · 第一册 · 2026-09-28
目标:把你已经掌握的JSON知识变成批量检查能力。你将亲手读取20条记录,定位类型、重复、路径、音频属性和质检声明问题,生成可追溯的问题报告。你不需要先学算法、模型训练或网站开发。
01 你要学到什么程度
采购Owner的核心是把需求、质量口径和交付责任说清楚。Python帮助你验证交付,而不是替你决定验收标准。
完成本课后,你应能独立做五件事:打开并运行脚本;读懂输入、规则和输出;修改一个已有检查条件;定位坏数据和运行错误;解释报告覆盖范围。
| 能力 | 本课要达到 | 现在不用追求 |
| 数据读取 | JSON、JSONL和本地文件路径 | 大规模数据平台 |
| 基础语法 | 变量、字典、列表、循环、条件、函数、异常 | 复杂面向对象设计 |
| 检查 | 缺失、类型、重复、文件存在、WAV属性 | 全模态自动质量判断 |
| 报告 | 行号、编号、规则、证据、分母与未检项 | 漂亮但无法复核的仪表盘 |
| 协作 | 向工程师提出可验证的规则需求 | 从零重写所有工具 |
你的毕业标准不是背语法,而是能拿着报告告诉供应商:哪条有问题,违反哪一版规格,证据在哪里,如何回源修复,以及复验什么。
02 第一次准备:文件夹、Python和终端
1. 解压完整学习包到一个自己找得到的位置,例如文档目录。暂时保留所有文件名和目录结构。
2. 双击“开始学习.html”阅读课程。HTML是教材,不会替你执行Python。
3. 在解压后的文件夹空白处右键,选择“在终端中打开”;也可以在资源管理器地址栏输入powershell并按回车。打开后应在课程根目录,能看到data、lessons、tools等文件夹。
4. 输入下面一行,回车:
python --version如果出现Python 3.x,确认版本至少3.10;建议用当前受支持版本。如果无法识别,再试:
py --version如果只有py有效,后续示例中的python统一换成py。如果两个都不可用,到Python官方下载页按Windows安装提示安装,关闭并重新打开终端,再检查。Windows安装方式可能变化,以官方Windows说明为准。不必为了这套课程卸载电脑已有的Python。
“终端”是输入运行命令的地方;“.py文件”是保存代码的地方。不要把python tools/validate_batch.py写进.py文件。看到>>>表示进入了Python交互窗口,输入exit()并回车,回到终端后再运行本课命令。
编辑代码可以使用已有的代码编辑器。没有编辑器时,记事本也能完成最初练习;保存为UTF-8,确认后缀确实是.py,不是.py.txt。编辑原始练习前先保存副本。
03 第一段程序:先运行,再改一行
在课程根目录的终端输入:
python lessons/01_hello.py预期看到欢迎语、总数20、问题记录占比0.85。这个占比是练习中17÷20,不是模型错误率,也不是合格语音比例。
print("开始你的第一次批量验收练习。")
total = 20
bad = 17
print("总数:", total)
print("问题记录占比:", bad / total)print负责显示。引号里的内容是文字;20是数字;total是变量名,表示给数字起个方便引用的名字;=是赋值。#后面的文字是注释,不会执行。
动手:把副本中的total改成100、bad改成3,再运行。应得到0.03。显示成3%可以写print(f"问题记录占比:{bad / total:.1%}")。f字符串用花括号嵌入计算结果;:.1%表示百分比保留一位小数。
采购思考:一条样本有三处问题,坏样本数仍是1,缺陷数是3。必须说明分子、分母及统计单位。
检查点:你能找到运行中的脚本、改一行、保存并重新运行,而不是只看截图。
04 把JSON翻译成Python
| 你熟悉的JSON | Python中的常见对应 | 注意 |
| 对象 {...} | 字典dict | 用字段名取值 |
| 数组 [...] | 列表list | 可按顺序循环 |
| 字符串 "th" | 字符串str | Python单引号也合法,JSON字段仍用双引号 |
| 数字 3、1.5 | int、float | "3"是文字 |
| true / false | True / False | 大小写不同 |
| null | None | 不等于空字符串或0 |
record = {"sample_id": "A001", "duration_seconds": 1.0}
print(record["sample_id"])
print(record.get("language"))第一行建立字典。record["sample_id"]取已有字段;字段不存在时会报KeyError。get取不到字段会返回None,让你继续判断。正式检查中,“缺字段”和“字段明确为null”可能需要分开记录;可用"language" in record判断是否存在。
records = [{"sample_id": "A"}, {"sample_id": "B"}]
print(records[0]["sample_id"])结果为A。Python从0计数,所以records[0]是第一条。给供应商的报告用真实文件行号,从1开始,别混淆。
动手:新建一个字典,加入language="th"和quality_checked=False,打印这两个字段。False只是一个声明值,不能据此知道真实审核过程。
05 条件和循环:让电脑重复检查
运行:
python lessons/02_records.py预期:A通过此项,B与C有问题。查看脚本:
for record in records:
value = record.get("duration_seconds")
if type(value) in (int, float) and value > 0:
print(record["sample_id"], "时长类型和正数检查通过")
else:
print(record["sample_id"], "时长有问题:", repr(value))for表示逐条处理;if表示如果;else表示否则;and表示两个条件都要满足。冒号后面缩进四个空格,表示哪些动作属于这个循环或判断。不要混用Tab和空格。
type看真实类型。这里不用简单的isinstance(value, int),因为Python里True也属于int的子类;在项目时长中把True当1秒会造成漏检。repr让字符串周围显示引号,便于看出"1.0"与1.0的区别。
动手:把条件补成“数字且大于0且不超过30秒”,加入一条31秒样本。预期31秒被拦截。真实项目的上限必须来自规格,不能照搬30秒。
06 路径和文件:为什么电脑说找不到
from pathlib import Path
root = Path(__file__).resolve().parents[1]
path = root / "data" / "broken.jsonl"from...import引入现成能力。Path处理文件路径;__file__是当前脚本;resolve得到完整位置;parents[1]从lessons里的脚本回到课程根目录。这里的/用于拼接路径,不是数学除法。
运行命令时,python lessons/03_read_jsonl.py中的路径仍相对于终端当前目录。因此请先在课程根目录打开终端。脚本内部则通过自身位置寻找data,减少切换目录造成的错误。
Windows完整路径有空格时,在命令中用双引号包住路径。不要随意把客户给的路径直接用于读写:需要限制在本批次目录内。../表示上一级目录,本课会拦截逃出audio目录的路径。
动手:找到data/broken.jsonl,用记事本打开。你应该看到三行;第二行故意多了逗号。
07 读取JSONL:坏一行,不能丢掉证据
运行:
python lessons/03_read_jsonl.py预期第1、3行读取成功,第2行解析失败,汇总成功2、失败1。必须继续看到第三行,且失败行不能从报告里消失。
with path.open(encoding="utf-8") as file:
for line_number, line in enumerate(file, start=1):
try:
record = json.loads(line)
except json.JSONDecodeError as error:
print("第", line_number, "行解析失败:", error.msg)
continuewith负责读完后关闭文件;encoding指定文字编码;enumerate同时给你行号和内容;json.loads把一行文字解析成Python对象;try尝试执行;except处理预期错误;continue转到下一行。
不要写“except: pass”把所有失败藏起来。它会让交付数量悄悄减少,也让采购Owner失去追责证据。解析成功也不代表字段、业务或内容正确。
动手:复制broken.jsonl为broken_fixed.jsonl,去掉第二行末尾多余逗号,把脚本副本的输入文件名改为新名字。预期成功3、失败0。保留原始错误文件作为练习证据。
08 函数:把一条规则写清楚
运行:
python lessons/04_function.py预期A通过;空字符串与缺失编号都提示错误。函数是一段可重复调用的检查。
def check_id(record):
value = record.get("sample_id")
if not isinstance(value, str) or not value.strip():
return "sample_id必须是非空字符串"
return Nonedef声明函数;record是输入;return是输出;strip去掉两端空白;or表示任一条件成立就进入错误分支。此函数只判断编号是否非空,不判断是否重复,也不判断编号对应的真实身份。
动手:加一条只包含三个空格的编号,应被拦截。再思考“A001”和“a001”是否重复:这是项目编号大小写规则,必须先约定,不能临时猜。
09 第一张规格表:先写规则,再运行工具
本课数据是合成测试音,不是ASR。音频目录有19个.wav扩展名文件:18个可读PCM WAV和1个损坏文件。第8个音频故意没有交付。其他文件即使没有被引用,也不代表已经完整检查;本课没有实现全量孤立文件盘点。
| 字段或属性 | 本课约定 | 自动检查范围 |
| sample_id | 非空字符串且批内唯一 | 两条重复记录都列出 |
| language | zxx,无语言内容 | 仅检查声明是否符合合成音题设 |
| duration_seconds | 数字,0<时长≤30秒 | 排除字符串、布尔值及非有限值 |
| audio_path | audio目录内的.wav | 存在、目录边界、扩展名 |
| quality_checked | 布尔值 | false暂缓;true仍需证据 |
| media_origin | synthetic_tone | 防止将合成音标成真实语音 |
| 文件属性 | 16000Hz、单声道、16-bit PCM | 标准库wave读取PCM WAV |
| 时长一致性 | 声明与实际差≤0.02秒 | 这是教学容差,不是行业统一标准 |
规则文件位于data/policy.json。修改规则会改变判定,所以报告必须保留规则版本。此课程没有把所有检查都做成可配置项:例如30秒上限写在脚本中。真实项目应审查并版本化完整脚本与配置,不只保存一个版本名字。
10 实战:运行20条批次检查
先预测会有哪些问题,再在课程根目录执行:
python tools/validate_batch.py预期统计:total_lines=20、parsed_objects=20、error_lines=17、hold_only_lines=1、no_configured_issue_lines=2、issue_count=18。
对应中文:共20行,20个对象解析成功;17行有错误;1行仅因未完成质检声明暂缓;2行未发现已配置规则问题;共18条问题记录,其中包含1条暂缓事项。
打开reports/my_run/report.html查看问题清单。report.json是机器可继续处理的版本。参考报告在reports/reference,避免与你的运行结果混淆。
终端命令运行结束,不等于批次通过。这个教学脚本即使发现数据缺陷也会正常结束;判定要读取报告中的统计和结论。将来接入自动流水线时,可请工程师约定错误退出码。
报告记录输入文件的SHA-256:它像文件内容的指纹,可帮助确认你复查的是不是同一版本;它不能证明数据授权、内容真实或采集人身份。
动手:找到第5行重复问题、第9行采样率问题、第11行暂缓问题,分别写出不同的处理动作。不能统一用“改成合格”解决。
11 读懂完整脚本,而不是背完它
按这个顺序阅读tools/validate_batch.py:
1. ROOT和main:输入从哪里来,报告写到哪里。--batch、--policy、--out是允许你指定的选项。
2. validate:主检查流程。rows保存解析成功的对象,issues保存发现的问题,ids记录同一编号出现的行号。
3. add:统一记录行号、样本编号、规则代码、说明和等级。统一结构让反馈能被复查。
4. number与no_duplicate_keys:拒绝布尔值伪装数字、NaN/Infinity以及同一对象重复字段名等歧义。
5. wave读取:观察真实文件属性,与policy比较。只适用于本课PCM WAV;不支持的格式应换工具,不要立刻指控供应商文件损坏。
6. errors和holds:使用集合set按行去重;先统计错误,再把同时有错误的行从“仅暂缓”中剔除,避免重复计数。
7. not_checked:明确没有检查的部分。这个列表不是免责话术,而是下一步工作清单。
本脚本面向20条的小批次,整文件读取并计算哈希;不是你们每月上万小时数据的生产平台。放大到生产时还要做流式读取、并发限流、日志、权限、版本、去重、抽样与人工复核流程。
12 学会改一条规则,并证明修改有效
练习A:复制policy.json为policy_strict.json,把duration_tolerance_seconds由0.02改成0.005,并把rule_version改成tone-training-v2-exercise。不要覆盖原文件。
练习B:复制batch.jsonl为batch_trial.jsonl,只把第19行duration_seconds改成1.01。按旧规则运行应无新增时长问题,按新规则运行应多出第19行问题。
python tools/validate_batch.py --batch data/batch_trial.jsonl --policy data/policy.json --out reports/trial_old
python tools/validate_batch.py --batch data/batch_trial.jsonl --policy data/policy_strict.json --out reports/trial_strict预期旧规则仍17个错误行、2个无配置问题行;新规则18个错误行、1个无配置问题行。第11行仍仅暂缓。修改时应先说明为何需要更严格的容差,再改变规则;这里仅为练习。
练习C:运行坏语法文件,检查第2行是否明确报告JSON_PARSE:
python tools/validate_batch.py --batch data/broken.jsonl --out reports/broken其他两行虽可解析,但缺少完整项目字段,因此也有规则错误。不能把“解析成功2条”说成“合格2条”。
13 遇到错误怎样处理
| 看到的提示 | 常见原因 | 你先做什么 |
| python无法识别 | 未安装或终端未更新 | 试py,检查安装后重开终端 |
| can't open file | 命令路径错或不在根目录 | 确认能看到lessons与tools |
| FileNotFoundError | 数据路径或解压结构有误 | 核对输入位置,不创建空文件凑数 |
| SyntaxError | 代码标点、引号或括号有错 | 查报错行及上一行,和原版比较 |
| IndentationError | 缩进层级不一致 | 使用四个空格,保留代码块结构 |
| JSONDecodeError | 输入JSON语法有错 | 看真实行号,回数据修复 |
| KeyError | 取不存在的字段 | 确认规格,必要时先判断存在性 |
| ModuleNotFoundError | 当前环境未安装所需包 | 核对使用哪个Python,再按第二册安装 |
| UnicodeDecodeError | 文件编码不匹配 | 核实编码,不用忽略错误掩盖损失 |
求助时提供:运行的命令、完整错误文字、输入的脱敏片段、Python版本、你希望得到的结果。不要只发“报错了”,也不要把客户原始数据和凭证上传到不被允许的服务。
14 七次练习安排与毕业作业
| 次数 | 建议任务 | 可检查产出 |
| 1 | 第1—3节 | 成功运行并修改欢迎语和比例 |
| 2 | 第4—5节 | 类型、布尔值和31秒边界练习 |
| 3 | 第6—7节 | 保留行号的坏JSONL报告 |
| 4 | 第8—9节 | 写清本批规格及不适用范围 |
| 5 | 第10—11节 | 自己生成的20条报告 |
| 6 | 第12—13节 | 新旧容差对比与故障说明 |
| 7 | 毕业作业 | 一页采购验收说明 |
每天可安排45—90分钟;卡住就围绕该检查点复练,不必赶进度。
毕业作业:不看讲师答案,写一份批次反馈,必须包括输入数量和版本、检查范围、17条错误与1条暂缓的统计口径、至少三条证据、供应商整改要求、未检内容、复验步骤和当前结论。
自评:能运行属于入门;能解释误判/漏判属于理解;能改规则并验证边界属于可协作;能结合合同和人工证据完成闭环才接近项目Owner工作。
15 向Coding、API、Agent迁移
你刚学的套路可以迁移:数据读取→规格检查→执行或观察→证据记录→人工判定。
Coding样本:检查题目、代码、测试和授权字段;在隔离环境运行测试;看测试是否覆盖边界。通过几条测试不等于代码完全正确。
API样本:检查工具名、参数名、参数类型、返回结构以及错误分支。JSON合法不等于工具调用正确。
Agent样本:检查动作是否被允许、调用顺序、工具结果、最终状态以及额外副作用。最终回答“已取消”不代表订单真的取消。
第二册附有本地模拟练习。你现在不必成为高级开发者,但应该能把“请帮我验一下”变成可测试的规则说明。
官方参考:Python入门教程、json模块、pathlib模块、wave模块。
一分钟自测
脚本显示“无配置规则问题”,能否直接通知客户全部合格?