Python 异常处理详解(Python 3.x)
异常处理是编程中应对错误的重要机制,Python 提供了灵活的异常处理语法,通过 try、except、else、finally 等关键字实现对错误的捕获、处理和资源清理。本文将详细介绍 Python 异常处理的基本用法、手动抛异常及常见场景。
基本异常处理结构
Python 异常处理的核心语法是 try...except,用于捕获并处理程序运行中可能出现的错误。
基础结构:try...except
1 | try: |
说明:
try块:包含可能触发异常的代码。except块:指定要捕获的异常类型,as e用于获取异常对象(包含错误信息)。- 若
try块中无异常,except块不执行;若发生指定类型的异常,跳至except块处理。
捕获多种异常
可使用多个 except 块处理不同类型的异常,或在一个 except 中捕获多个异常:
1 | try: |
执行逻辑:
- 程序按顺序检查
except块,匹配到第一个对应异常类型后执行,不再检查后续块。 - 建议先捕获具体异常(如
ValueError),再捕获通用异常(如Exception),避免覆盖特定异常。
捕获所有异常(不推荐)
使用 except Exception 可捕获所有非系统退出的异常(不包括 KeyboardInterrupt 等):
1 | try: |
注意:过度使用通用异常捕获可能隐藏代码逻辑错误,建议仅在需要统一处理所有异常的场景使用(如日志记录)。
else 子句:无异常时执行
else 子句可选,用于定义当 try 块中无异常时执行的代码:
1 | try: |
示例执行:
- 若输入
5(无异常):输出你输入的正数是:5。 - 若输入
-3(触发异常):输出错误:必须输入正数。
finally 子句:必执行的清理操作
finally 子句用于定义无论是否发生异常都必须执行的代码,通常用于释放资源(如关闭文件、网络连接):
1 | file = None |
说明:
- 即使
try或except块中包含return,finally仍会执行。 - 常用于资源清理,确保资源不会因异常而未释放。
手动抛出异常(raise)
使用 raise 关键字可手动触发异常,用于在满足特定条件时主动报错(如参数校验)。
基本用法
1 | def check_age(age): |
抛出自定义异常
除了 Python 内置异常(如 ValueError、TypeError),还可定义自定义异常类:
1 | # 定义自定义异常(继承自 Exception) |
自定义异常优势:使异常类型更贴合业务逻辑,便于精准捕获和处理。
常见内置异常类型
Python 提供了多种内置异常,以下是常用类型:
| 异常类型 | 说明 | 示例场景 |
|---|---|---|
ValueError |
值无效 | int("abc")(字符串无法转整数) |
TypeError |
类型错误 | "2" + 3(字符串与整数相加) |
IndexError |
序列索引越界 | [1,2][5](列表索引超出范围) |
KeyError |
字典键不存在 | {"a":1}["b"](访问不存在的键) |
FileNotFoundError |
文件不存在(打开文件时) | open("nonexist.txt") |
ZeroDivisionError |
除数为 0 | 1 / 0 |
AttributeError |
对象属性不存在 | [].nonexist_method() |
异常处理最佳实践
- 捕获具体异常:避免使用
except Exception捕获所有异常,应针对性捕获可能发生的异常(如FileNotFoundError)。 - 提供有用的错误信息:在异常处理中说明错误原因,便于调试(如
print(f"文件 {filename} 不存在"))。 - 使用
finally释放资源:文件、网络连接等资源必须在finally中关闭,防止资源泄露。 - 合理使用自定义异常:对于业务特定的错误(如 “分数超出范围”),定义自定义异常可提高代码可读性。
- 避免过度使用异常:异常处理开销较高,可通过条件判断避免的错误(如检查除数是否为 0),无需依赖异常。