Python: 异常处理
最后更新:2026-09-22
程序运行中总会出现意外情况——文件不存在、网络断开、用户输入了非法数据……如果不处理这些"异常",程序就会崩溃退出。异常处理让你的程序能从错误中恢复,给用户友好的提示,而不是留下一堆看不懂的错误信息。
1. 什么是异常
异常(Exception)就是程序运行时发生的错误。遇到异常而没处理,程序就会终止:
PYTHON
# 这段代码会崩溃
# print(10 / 0) # ZeroDivisionError: division by zero
# int("abc") # ValueError: invalid literal for int()
# open("不存在的文件.txt") # FileNotFoundError
用 try-except 可以优雅地处理这些错误:
▶ 示例:try-except 处理除零和输入错误
▶ 试一试运行示例:
TEXT
📖 仅展示
请输入一个数字:abc
输入的不是有效数字!
💡 异常处理的哲学: 不是用
try 去"预测所有可能的错误",而是"先把事情做了,遇到问题再处理"。Python 社区的说:"It's easier to ask for forgiveness than permission"(EAFP——请求原谅比请求许可更容易)。
2. try-except 的完整结构
▶ 示例:try-except-else-finally 完整结构
▶ 试一试输出:
TEXT
📖 仅展示
文件不存在!
文件内容不是有效的数字!
读取并转换成功!
清理工作:关闭文件
| 部分 | 什么时候执行 | 用途 |
|---|---|---|
try |
总是 | 放可能出错的代码 |
except |
发生指定异常时 | 处理错误 |
else |
没有异常时 | 成功后的逻辑 |
finally |
总是(不管有没有异常) | 清理资源(关闭文件/释放连接) |
3. 常见异常类型
PYTHON
# ZeroDivisionError —— 除零
# int("abc") # ValueError —— 值错误
# [1, 2][5] # IndexError —— 索引越界
# {"a": 1}["b"] # KeyError —— 键不存在
# open("x.txt") # FileNotFoundError —— 文件不存在
# 10 + "hello" # TypeError —— 类型错误
# import nonexistent # ModuleNotFoundError —— 模块不存在
(1) 捕获所有异常(但不推荐)
▶ 示例:捕获异常的正确与错误方式
▶ 试一试输出:
TEXT
📖 仅展示
出错了
⚠️ 裸
except: 不推荐—— 它会捕获 KeyboardInterrupt(Ctrl+C)和 SystemExit 等系统异常,导致程序无法正常终止。用 except Exception as e 更合适。最好的做法是只捕获你预期会发生的具体异常类型。
4. raise:主动抛出异常
有时候你需要主动告诉调用方"出错了",用 raise:
▶ 示例:raise 抛出异常
▶ 试一试输出:
TEXT
📖 仅展示
# 函数定义成功
(1) 密码强度检查示例
▶ 示例:raise 检查密码强度
▶ 试一试输出:
TEXT
📖 仅展示
# 函数定义成功
💡 什么时候用
raise? 当函数遇到了"不应该发生的"情况时——参数值非法、前置条件不满足、依赖的资源不可用。抛出异常让调用方决定怎么处理,而不是在函数内部偷偷吞掉错误。
5. 自定义异常类
你可以创建自己的异常类型,让错误信息更精确:
▶ 示例:自定义异常与银行取款
▶ 试一试输出:
TEXT
📖 仅展示
# 函数定义成功
💡 自定义异常让你的代码更清晰—— 调用方可以精确处理不同类型的错误。直接继承
Exception 类即可,通常只需要写一个类名,不需要额外的方法。
6. logging:专业的错误记录
用 print() 输出错误信息在简单脚本里还行,但在正式项目中,应该用 logging 模块:
▶ 示例:logging 配置与使用
▶ 试一试运行结果(同时写入文件和控制台):
TEXT
📖 仅展示
2026-06-23 16:00:00,123 [INFO] 程序启动成功
2026-06-23 16:00:00,124 [WARNING] 磁盘使用率85%
2026-06-23 16:00:00,124 [ERROR] 数据库连接失败
💡 用
logging 代替 print() 的好处: ① 可以同时输出到控制台和文件。② 有级别控制(开发时全开,上线后只显示 WARNING 以上)。③ 自动带时间戳。④ 不需要在发布前删掉一堆 print()。
7. 常见应用场景
- 用户输入验证:用
try-except处理int()转换错误,给用户友好的提示。 - 文件操作:用
try-except处理文件不存在、权限不足等错误。 - 网络请求:处理超时、连接失败、数据解析错误。
- 数据库操作:处理连接失败、SQL 语法错误、唯一约束冲突。
- API 开发:用自定义异常精确区分不同类型的错误。
❓ 常见问题
Q
except Exception as e 中的 as e 是什么意思?A
as e 把捕获到的异常对象赋值给变量 e,这样你就可以查看异常的具体信息——print(e) 显示错误描述,type(e).__name__ 显示异常类型名。不加 as e 也能捕获异常,但看不到详细错误信息。Q 什么时候应该用异常,什么时候应该用 if 判断?
A 可以用 if 预判的错误就用 if(比如检查除数为零)。无法预判的错误用 try-except(比如网络请求、文件操作)。Python 社区的 EAFP 风格倾向用 try——不过这是一个审美问题,两种方式各有适用场景。
📖 小节
- 异常是程序运行时发生的错误,用
try-except处理 - 结构:
try→except(按具体异常类型)→else(无异常)→finally(总是执行) - 常见异常:
ValueError、TypeError、FileNotFoundError、ZeroDivisionError、IndexError、KeyError raise主动抛出异常,让调用方处理错误- 自定义异常类继承
Exception,精确区分错误类型 logging模块替代print(),支持级别控制、文件输出、时间戳
📝 作业
-
基础题(难度⭐):写一个程序,让用户输入两个数字,计算它们的除法。用
try-except处理ValueError(输入不是数字)和ZeroDivisionError(除数为零),分别给出友好的错误提示。 -
进阶题(难度⭐⭐):写一个函数
read_int_from_file(filename),读取文件中的第一个数字并返回。用 try-except 处理:文件不存在、文件内容不是有效数字、文件为空等错误情况。每种情况返回不同的错误提示。 -
挑战题(难度⭐⭐⭐):写一个"安全的计算器"程序。用户输入表达式(如
10 / 3),程序计算并输出结果。要求:① 用try-except处理除零、值错误、类型错误。② 用logging记录每次的计算操作(INFO)和错误(ERROR)到calculator.log文件。③ 支持exit退出。提示:用eval()计算表达式(注意安全问题,此练习场景可用)。