文章
学习
从 Python 到 Data/AI 一年计划成果第 7 / 10 篇 对应计划

Week 3 学习成果|异常、traceback 与 Debug 起步

Week 3 的实际产出:Day 1 异常与 traceback 训练,能读 traceback、区分调用帧与抛出点、解释 KeyError / AttributeError / TypeError / ZeroDivisionError 的成因,并用 .get() 修复 KeyError。

PythonWeek3异常处理tracebackraise异常链debugging学习成果

本篇对应 Week 3 学习计划,与一年学习计划总纲 Phase I 的 Week 3 · 异常、测试与 Debugging(等级 L2)一致,按总纲 Part II「每周固定执行模板」编排。计划篇保留任务与要求,这里放实际做出来的东西和训练记录。目前有书面成果的是 Day 1,Day 2–5 完成后再补进来。

🎯 本周目标

L1

  • ✅ 能读懂 traceback,讲清 Exception / traceback / raise / try-except-finally 的语义

L2

  • 🟡 三类测试(boundary / invalid input / exception)与 fixture / mock 尚未产出书面成果

L3

  • 总纲本周不设 L3

📚 Core Knowledge

  • 异常是什么、异常对象与 traceback 的结构
  • traceback 的读法:从下往上读,区分调用帧与抛出点,过滤库帧
  • raise 主动抛异常与异常链 raise ... from ...
  • try / except / else / finally 的执行顺序
  • LBYL 与 .get() 两种修 bug 的字典写法
  • 四类常见异常的成因:KeyError / AttributeError / TypeError / ZeroDivisionError

✍️ Human Core

  • 读 4 个 traceback,能说出异常类型、消息、抛出位置
  • 区分“调用帧”和“抛出点”
  • 能解释 KeyError / AttributeError / TypeError / ZeroDivisionError 的成因
  • 能修复 KeyError,用 .get() 替代直接索引
  • boundary test / invalid input test / exception test(Day 2)

🤖 AI Build

  • AI 扩充测试、review 测试、人为制造 bug(Day 4–5)

🧪 Experiment

Hypothesis

  • 反复读 traceback 并归纳异常成因,能建立“从异常类型反推根因”的直觉。

Experiment

  • Day 1 读 4 个 traceback,逐条拆出异常类型、消息、抛出位置,并对比调用帧与抛出点。

Result

  • 4 个 traceback 均能定位异常类型与抛出点;能解释 KeyError / AttributeError / TypeError / ZeroDivisionError 的成因;KeyError 用 .get() 修复。

Conclusion

  • 读 traceback 的关键是“从下往上 + 只看自己写的帧”;traceback 只给事实(类型 / 消息 / 位置),不给原因和修法,这两步得自己判断。

📝 数智工程师考试映射

  • 异常处理与错误传播
  • traceback 阅读与根因定位

✅ Acceptance

L1

  • 能读懂 traceback,定位到出错文件与行号
  • 能区分“调用帧”和“抛出点”

L2

  • 能独立编写 boundary / invalid input / exception test(Day 2)
  • 能按要求完成 Debug 四步法(Day 4)

L3

  • 总纲本周不设 L3

🧠 本周最重要的问题

看到 traceback 后,能不能不靠猜,走完「定位 → 解释 → 原因 → 修复」四步?

❓ 尚未解决

  • Day 2–5 的三类测试、fixture / mock、四类 bug 实验尚未产出书面成果

📊 Final Level

L2(进行中)

Day 1 成果|异常、traceback 与 Debug 起步

对应计划:Day 1|异常 + traceback 复习 + 读 traceback 训练

异常是什么

程序做不到某件事时,抛出异常对象。没人接住,程序中断并打印 traceback。

读 traceback

Traceback (most recent call last):
  File "demo.py", line 10, in <module>      ← 最早发生
    result = parse("abc")
  File "demo.py", line 5, in parse          ← 最近发生(抛出点)
    return int(s)
ValueError: invalid literal for int() ...   ← 异常类型 + 消息

读法:

  • 从下往上读
  • 最下面:异常类型和消息
  • 往上找:哪一行抛的(最靠近异常类型的那一帧)
  • 再往上:谁调用了谁
  • 找“自己写的代码”

traceback 里混着标准库 / 第三方库的帧:找自己项目的文件名,跳过库的帧。

traceback 不告诉你的事:

  • 为什么这行会出错
  • 是数据问题还是代码问题
  • 怎么修

这三件事得自己判断。

raise 主动抛异常

raise ValueError("年龄不能为负数")

常见用途:参数校验、不支持输入、记录后重抛。

异常链 raise ... from ...

try:
    int("abc")
except ValueError as e:
    raise RuntimeError("配置解析失败") from e
  • 对外暴露 RuntimeError
  • ValueError 保留在 traceback 里当根因
  • 用于分层转换:底层技术错误 → 上层业务错误

try / except / finally 执行顺序

情况顺序
成功try → else → finally
失败被捕获try → except → finally
失败没捕获try → finally,异常继续抛

finally 里的 return 会覆盖 try 里的 return。

修 bug 的两种字典写法

LBYL:先检查

def get_user(users, user_id):
    if user_id not in users:
        return None
    return users[user_id]

.get():字典内置,最简洁

def get_user(users, user_id):
    return users.get(user_id)

.get(key, default) 规则:

  • 键存在 → 返回真实值
  • 键不存在 → 返回 default(不写则 None)
  • 永不抛 KeyError

Debug 四步法

1. 定位:哪一行?哪个文件?
2. 解释:这行在干什么?为什么出错?
3. 原因:根本原因是什么?
4. 修复:改什么?怎么验证改对了?

今日训练完成

  • 读了 4 个 traceback,能说出异常类型、消息、抛出位置
  • 区分了“调用帧”和“抛出点”
  • 能解释 KeyError / AttributeError / TypeError / ZeroDivisionError 的成因
  • 能修复 KeyError,用 .get() 替代直接索引

来源与延伸阅读

  1. 01Week 1 学习计划|Python 对象模型与数据结构week-1计划
  2. 02一年学习计划:从 Python 到 Data/AI 系统的 52 周计划
  3. 03Week 1 学习成果|复杂度实测、对象模型与数据结构实战week-1成果
  4. 04Week 2 学习计划|Python 函数、作用域、闭包与模块化week-2计划
  5. 05Week 2 学习成果|闭包、decorator 与工程化重构week-2成果
  6. 06Week 3 学习计划|异常、测试与 Debuggingweek-3计划
  7. 07Week 3 学习成果|异常、traceback 与 Debug 起步week-3成果
  8. 08Week 4 学习成果|Big-O 与四类基础算法week-4成果
  9. 09Week 5 学习成果|Stack、Queue 与 MinHeapweek-5成果
  10. 10Week 6 学习成果|图算法与 Python Engineering Toolkitweek-6成果