第 31 课 · 阶段五 · 文件与异常
异常处理 try / except
程序总会遇到意外:文件不存在、输入不是数字、除以 0。这一课学会用 try/except 优雅地兜住错误,而不是让程序直接崩溃。
🎯 学完本课你将掌握
- 理解异常的概念与常见异常类型
- 掌握 try/except/else/finally 四件套
- 会用 raise 主动抛出异常
一、什么是异常
异常是程序运行时的错误事件。不处理时程序会中断并打印一大段红色的报错信息(traceback);用 try/except 可以捕获并从容处理。
二、最常见的几种异常
| 异常类型 | 触发场景 |
|---|---|
| ValueError | int("abc") 转换失败 |
| TypeError | 不同类型不兼容运算 |
| ZeroDivisionError | 除以 0 |
| IndexError | 索引越界 |
| KeyError | 字典键不存在 |
| FileNotFoundError | 文件不存在 |
三、基本用法
try except 基础.py
1try:2 num = int(input("请输入一个数字:"))3 print(100 / num)4except ValueError:5 print("输入的不是数字!")6except ZeroDivisionError:7 print("不能除以 0!")8print("程序没有崩溃,继续执行")四、捕获所有异常(不推荐单独使用)
多异常.py
1try:2 x = 1 / 03except (ZeroDivisionError, TypeError) as e:4 print("发生异常:", e) # 打印异常信息56try:7 risky()8except Exception as e:9 print("未知异常:", e) # 兜底捕获⚠️ 注意
except Exception 能兜住几乎所有异常,但会掩盖真正的 Bug。正确做法:尽量捕获具体类型,最后再考虑通用兜底。
五、else 与 finally
else finally.py
1try:2 n = int(input("数字:"))3except ValueError:4 print("输入无效")5else:6 print("没有异常,计算结果:", n * 2) # 仅在无异常时执行7finally:8 print("无论有没有异常,finally 都会执行")✅ 要点
else:没异常才执行;finally:无论如何都执行(常用于关闭资源、写日志)。
六、主动抛出异常:raise
raise 用法.py
1def set_age(age):2 if age < 0 or age > 150:3 raise ValueError("年龄不合法:%d" % age)4 return age56try:7 set_age(200)8except ValueError as e:9 print("捕获到:", e)七、实战:健壮的文件读取
健壮读取.py
1filename = input("输入文件名:")2try:3 with open(filename, "r", encoding="utf-8") as f:4 data = f.read()5except FileNotFoundError:6 print("文件不存在,请检查名字")7except PermissionError:8 print("没有权限读取该文件")9except Exception as e:10 print("其他错误:", e)11else:12 print("文件内容:", data[:100])八、常见错误与解决
常见错误与解决
| 错误现象 | 原因 / 解决方法 |
|---|---|
捕获了异常但没提示 | except 块里没写处理逻辑,至少要 print 或记日志。 |
finally 里的 return 覆盖了 try 的 return | finally 一定会执行,别在里面写 return,会吞掉正常结果。 |
裸 except 被 PEP8 警告 | 使用 except Exception 或具体异常类型。 |
✍️ 小练习
写一个除法函数 safe_div(a,b),内部捕获 ZeroDivisionError 并返回 "除数不能为0";再写一个程序让用户反复输入直到输入合法数字。
📌 本节小结
异常处理四件套:try 放风险代码、except 捕获处理、else 无异常才执行、finally 必执行。具体异常优先,raise 主动抛错。程序从此不再一碰就碎。