Python 的异常处理通过 try 复合语句实现,完整语法包含四个子句:try、except、else、finally。它们的组合能让你既优雅地应对错误,又保证资源正确释放。
基本结构
try:
# 可能抛出异常的代码
except SomeException as e:
# 捕获到特定异常时的处理
else:
# 没有异常发生时执行
finally:
# 无论是否异常都会执行(通常用于清理资源)
各子句详解
1. try 子句
- 执行的代码块,一旦某条语句抛出异常,后续语句就不再执行,直接跳转到匹配的
except去处理。
try:
result = 10 / 0 # 抛出 ZeroDivisionError
print("这行不会执行")
except ZeroDivisionError:
print("除数不能为零")
2. except 子句
- 可以捕获一个或多个异常类型,也可以不指定类型(捕获全部)。
- 支持
as绑定异常实例,以获取错误详情。
try:
num = int(input("输入数字: "))
result = 100 / num
except ValueError:
print("输入的不是有效数字")
except ZeroDivisionError:
print("不能输入0")
except (TypeError, KeyError) as e:
print(f"类型或键错误: {e}")
except Exception as e: # 兜底,捕获其他未预料异常
print(f"发生未知错误: {e}")
- 要点:
except按顺序匹配,一旦匹配成功,后面的except就不会再检查。所以应当把更具体的异常放在前面,更泛化的(如Exception)放在最后。
3. else 子句
- 只有
try块没有抛出任何异常时才会执行。 - 典型用途:把只应在无异常时执行的代码从
try中移出来,让try块只包含可能出错的语句,意图更清晰。
try:
f = open("data.txt", "r")
except FileNotFoundError:
print("文件不存在")
else:
content = f.read() # 只有文件打开成功,才读取
print(content)
f.close()
- 对比:如果不使用
else,你可能把content = f.read()也放在try中,但一旦读取时出问题(磁盘坏道等),就会被误认为是文件不存在,异常处理变混乱。else让try的职责更单一。
4. finally 子句
- 无论是否发生异常,也不管异常是否被捕获,
finally中的代码一定会执行(即使try/except中有return或break,也会先执行finally)。 - 适用于资源释放:关闭文件、释放锁、关闭数据库连接等。
f = None
try:
f = open("data.txt", "r")
data = f.read()
except FileNotFoundError:
print("文件不存在")
finally:
if f:
f.close() # 确保文件一定被关闭
print("清理完成")
更简洁的方式是使用 with 语句(上下文管理器),它自动帮你处理 finally 的清理逻辑。这也是处理文件等资源的推荐做法。
# 推荐:自动关闭文件
try:
with open("data.txt", "r") as f:
data = f.read()
except FileNotFoundError:
print("文件不存在")
组合使用原则
try必须和至少一个except或finally同时出现。else必须跟在所有except之后,finally之前。- 常用顺序:
try→except(s) →else→finally。
捕获异常的最佳实践
- 精确捕获:尽量捕获具体异常类型,避免裸
except:,它会吞掉系统退出异常(SystemExit、KeyboardInterrupt)等,导致程序无法正常终止。 - 记录而不是忽略:如果必须捕获异常且不做处理,至少记录日志,否则问题极难排查。
- 不建议用异常控制正常流程:异常处理有性能开销,应只用于真正的“异常情况”,而不是代替条件判断。
- 不要无脑捕获所有异常:有时应当让异常向上传播,由更上层的调用者处理。
# 不好:吞掉一切异常
try:
do_something()
except:
pass
实际场景示例
场景1:读取配置文件,不存在则用默认值
try:
with open("config.json", "r") as f:
config = json.load(f)
except FileNotFoundError:
config = {"host": "localhost", "port": 80}
except json.JSONDecodeError:
print("配置文件格式错误,使用默认配置")
config = {"host": "localhost", "port": 80}
场景2:处理 API 调用中的网络错误和响应错误
try:
response = requests.get("https://api.example.com/data", timeout=5)
response.raise_for_status() # 4xx/5xx 抛异常
except requests.Timeout:
print("请求超时")
except requests.ConnectionError:
print("网络连接问题")
except requests.HTTPError as e:
print(f"HTTP 错误: {e.response.status_code}")
else:
data = response.json() # 只有成功才解析数据
print(f"获取到 {len(data)} 条记录")
finally:
print("请求结束")
掌握 try/except/else/finally 的组合运用,能让你的程序在应对不可预测的错误时既健壮又清晰,是写出生产级 Python 代码的基本功。