第7章 异常与文件
try-except-finally、自定义异常、文本/CSV/JSON 文件读写与 with 语句。
本章学习目标
- 能捕获并处理常见异常
- 能自定义异常类型
- 能用 with 安全读写文本文件
- 能用 json / csv 模块存取结构化数据
本章导览
核心内容
7.1
异常处理
程序不可能永远顺利:用 try-except 接住错误,给出可读提示而不是崩掉。
能捕获常见异常能用 else / finally能自定义异常并主动抛出
知识点
try-except
- try: 放可能出错的代码;except 具体类型 as e: 处理。
- 捕获要具体(ValueError、FileNotFoundError),不要一把抓 Exception 然后什么都不做。
- 多个 except 从上往下匹配。
else 与 finally
- else 在 try 没出错时执行;finally 无论如何都执行(关文件、释放资源)。
- with 语句能自动关闭资源,比手写 finally 更省事。
自定义异常
- class ScoreError(Exception): pass 定义业务异常。
- raise ScoreError("成绩不能为负") 主动抛出。
- 让调用方知道“错在哪、怎么改”。
代码示例
▶ 捕获并提示
def parse_score(text):
try:
score = float(text)
if score < 0 or score > 100:
raise ValueError("成绩必须在 0~100 之间")
return score
except ValueError as e:
print(f"输入有误:{e}")
return None
print(parse_score("89.5"))
print(parse_score("abc"))👀 运行结果
89.5 输入有误:could not convert string to float: 'abc'
▶ 自定义异常
class ScoreError(Exception):
pass
try:
raise ScoreError("成绩不能为负")
except ScoreError as e:
print("业务异常:", e)👀 运行结果
业务异常: 成绩不能为负
常见错误
⚠️ 踩坑与解决
except 顺序错(父类在前)
→ except Exception 写在前面把后面的挡住了;具体异常放前面except 里又抛错导致信息丢失
→ 处理里做了同样会失败的操作;处理逻辑尽量简单,必要时 raise 原样抛出
💡 except 里至少打印或记录错误信息,静默吞掉异常是线上事故的常见源头。
7.2
文件读写
with open(...) as f: 是标准写法,自动关文件、不会忘。
能读写文本文件能指定编码避免乱码能逐行处理大文件
知识点
基本读写
- with open("a.txt", "r", encoding="utf-8") as f: text = f.read()。
- 写入模式 "w" 会清空原文件,"a" 是追加。
- 一次性 read() 只适合小文件;大文件用 for line in f: 逐行。
编码问题
- Windows 默认 GBK,读 UTF-8 文件会乱码,务必写 encoding="utf-8"。
- 写文件同理,两端编码一致才不会出问题。
路径
- 用相对路径时注意“当前工作目录”,不是脚本所在目录。
- pathlib.Path(__file__).parent / "data.txt" 能拿到脚本旁边的文件。
代码示例
▶ 写文件
with open("scores.txt", "w", encoding="utf-8") as f:
f.write("张三,89\n")
f.write("李四,92\n")
print("写入完成")👀 运行结果
写入完成
▶ 逐行读并统计
total, n = 0, 0
with open("scores.txt", encoding="utf-8") as f:
for line in f:
name, score = line.strip().split(",")
total += int(score)
n += 1
print(f"共 {n} 人,平均 {total / n:.1f}")👀 运行结果
共 2 人,平均 90.5
常见错误
⚠️ 踩坑与解决
FileNotFoundError: [Errno 2] No such file or directory
→ 路径不对或文件不存在;用绝对路径或 pathlib 定位UnicodeDecodeError: 'gbk' codec can't decode
→ 没指定 encoding;统一加 encoding="utf-8"
💡 读写文件三件套:with、encoding="utf-8"、strip() 去换行符。
7.3
JSON 与 CSV
程序之间交换数据最常用的两种格式:JSON(结构化)与 CSV(表格)。
能用 json 模块读写能用 csv 模块批量处理能处理中文与编码
知识点
JSON
- json.load(f) 读成 dict/list,json.dump(obj, f, ensure_ascii=False) 写。
- ensure_ascii=False 才能显示中文;indent=2 让文件可读。
- JSON 的键必须是字符串,值为 null/true/false。
CSV
- csv.reader 按行读成列表;csv.DictReader 读成字典(推荐)。
- csv.writer / DictWriter 写入;newline="" 防止空行。
- Excel 导出的 CSV 有时带 BOM,可用 encoding="utf-8-sig"。
格式选择
- 有嵌套结构、要给程序读 → JSON。
- 一列一行的表格、要给 Excel 看 → CSV。
代码示例
▶ 读写 JSON
import json
data = {"name": "张三", "scores": [89, 92]}
with open("stu.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
with open("stu.json", encoding="utf-8") as f:
print(json.load(f)["scores"])👀 运行结果
[89, 92]
▶ 读 CSV 并统计
import csv
with open("scores.csv", encoding="utf-8") as f:
rows = list(csv.DictReader(f))
print(len(rows), rows[0]["姓名"] if rows else "")👀 运行结果
(按实际文件输出)
常见错误
⚠️ 踩坑与解决
json.decoder.JSONDecodeError
→ 文件不是合法 JSON(多余逗号、单引号);用在线工具校验,或输出写入内容检查写入中文变成 \u5f20\u4e09
→ dump 时没加 ensure_ascii=False;加上该参数
💡 不确定结构时,先把数据 print(json.dumps(obj, ensure_ascii=False, indent=2)) 看一眼。