第7章 异常与文件

try-except-finally、自定义异常、文本/CSV/JSON 文件读写与 with 语句。

健壮性第10-11周3 讲6 段示例代码

本章学习目标

  • 能捕获并处理常见异常
  • 能自定义异常类型
  • 能用 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("成绩不能为负") 主动抛出。
  • 让调用方知道“错在哪、怎么改”。

代码示例

▶ 捕获并提示
PYTHON
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'
▶ 自定义异常
PYTHON
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" 能拿到脚本旁边的文件。

代码示例

▶ 写文件
PYTHON
with open("scores.txt", "w", encoding="utf-8") as f:
    f.write("张三,89\n")
    f.write("李四,92\n")
print("写入完成")
👀 运行结果
写入完成
▶ 逐行读并统计
PYTHON
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
PYTHON
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 并统计
PYTHON
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)) 看一眼。