小白学 Python
课程GitHub
© 2026 小白学 Python · 基于 walter201230/Python 教程
课程目录GitHub
Python 环境加载中…
异常处理0 / 5
12345

异常处理

5 道练习题·预计 40 分钟·做对一题解锁下一段

教学 01 / 06· 已读

第十九节:异常处理

写代码这件事,最让新手崩溃的瞬间是哪种?想象一下:你刚学完语法,兴冲冲写了几十行代码,按下回车,结果终端弹出一坨红字:

Traceback (most recent call last):
  File "main.py", line 5, in <module>
    print(10 / 0)
ZeroDivisionError: division by zero

一脸懵。这玩意儿是啥?我哪里写错了?为啥程序就崩了?

其实啊,这就是 Python 的「异常机制」在工作。程序遇到了它处理不了的情况,比如除以零、读不存在的文件、把字符串当数字加,于是它就「抛」一个异常出来,整个程序停下来,告诉你:「我不干了,你来收拾」。

可是真实世界里的程序怎么可能因为一个小问题就停摆?银行 ATM 你输错密码三次它会提示,不会直接死机;网页加载图片失败会显示一个占位图,不会整页白屏;微信收消息网络不通它会重试,不会闪退。这些场景背后,全都是「异常处理」在做事。

程序为什么会「炸」

我们先从最简单的例子开始:

python
print(10 / 0)

输出:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero

这就叫「异常」。Python 在执行 10 / 0 的时候发现:除数是零,这事儿数学上没法干,于是它创建了一个 ZeroDivisionError 对象,把这个对象「抛」出来。如果没人接,这个异常就会一路冒泡到最外层,最后由 Python 解释器接住,打印 traceback,然后退出程序。

再看几个:

python
nums = [1, 2, 3]
print(nums[10])
# IndexError: list index out of range

d = {'name': '小明'}
print(d['age'])
# KeyError: 'age'

每一种「错误」都有它自己的名字。这些名字就是异常的「类型」,是 Python 内置的一组类。它们不是给你看着玩的,是供你用来「精确捕捉」的——不同类型用不同的处理方式。

这一节要学什么

Python 早就给我们准备好了一整套工具:

  • try / except:基本捕获结构
  • 多种异常处理:一段代码可能抛多种错
  • else / finally:完整四件套
  • raise:主动抛出异常
  • 自定义异常类:让错误也变成代码结构的一部分

学完这一节,再也不怕红字 traceback。

教学 02 / 06

一、最朴素的 try / except

把第一段代码改造一下。我们不希望除以零让整个程序崩溃,而是希望它在崩之前给出一句友好的提示,然后继续往下走:

python
try:
    result = 10 / 0
    print(result)
except ZeroDivisionError:
    print('哎呀,除数不能是零')

print('程序继续运行')

输出:

哎呀,除数不能是零
程序继续运行

是不是发现,红字 traceback 没了,程序也没崩,最后那句「程序继续运行」也乖乖打印出来了。

三个关键点

try / except 的语法就这么简单,记住三件事:

  • try: 块里放「可能出问题」的代码
  • except XxxError: 块里放「出了问题该怎么办」的代码
  • 如果 try 块没出错,except 块完全跳过,跟没写一样

一个常被忽略的细节

如果 try 块里有十行代码,第三行炸了,后面七行还会执行吗?

答案是:不会。Python 一旦在 try 里发现异常,就立刻跳到对应的 except,try 里剩下的代码全部跳过。我们写个例子验证一下:

python
try:
    print('第一行')
    print(10 / 0)
    print('第三行——这一行不会被执行')
except ZeroDivisionError:
    print('我接住了')

print('程序继续')

输出:

第一行
我接住了
程序继续

果然,「第三行」没打印出来。这个细节非常重要,很多新手 debug 半天找不到问题,就是因为以为 try 里抛了异常之后下面还会跑——不会的,跳过了。

练习 1 / 5·safe_divide:用 try/except 处理除零题目有问题?

请写一个函数 safe_divide(a, b):

  • 正常情况下返回 a / b
  • 如果 b 是 0,捕获 ZeroDivisionError,打印 '除数不能是零',然后返回 None

然后调用:

print(safe_divide(10, 2))
print(safe_divide(10, 0))

输出应该是:

5.0
除数不能是零
None

注意 safe_divide(10, 0) 因为返回 None,外层 print 会打印 None。

main.py
可编辑
🔒做对当前题解锁下一段 ·0/5
本章目录

异常处理

  1. 教学 01第十九节:异常处理
  2. 教学 02一、最朴素的 try / except
  3. 练习 1safe_divide:用 try/except 处理除零
  4. 教学 03二、一次捕获多种异常
  5. 练习 2 🔒多 except:处理 ValueError
  6. 教学 04三、else 和 finally——四件套补全
  7. 练习 3 🔒finally:清理一定要跑
  8. 教学 05四、主动抛异常——raise
  9. 练习 4 🔒raise:主动抛异常
  10. 教学 06五、自定义异常类
  11. 练习 5 🔒自定义异常:InvalidScoreError
← 上一章18 · pathlib:现代化路径处理
异常处理
下一章 →20 · dataclass