2.10 异常处理
2.10.1 异常的概念
2.10.1.1 什么是异常
异常是在程序执行过程中发生的错误条件,它中断了正常的程序流程。
2.10.1.2 异常的常见类型
Python中有多种内置异常类型,如ValueError、TypeError、IndexError等。
2.10.1.3 异常的传播和捕获机制
异常会向上传播直到被捕获,如果没有被捕获,它会导致程序终止。
2.10.2 try-except 语句
2.10.2.1 基本的 try-except 使用
try-except语句用于捕获和处理异常。
代码演示:
try:
x = 1 / 0
except ZeroDivisionError:
print("不能除以零")
输出:
不能除以零
2.10.2.2 多个 except 分支处理不同类型的异常
可以有多个except分支来处理不同类型的异常。
代码演示:
try:
x = int(input("请输入一个整数: "))
if x < 0:
raise ValueError("不能为负数")
except ValueError as e:
print("值错误:", e)
except Exception as e:
print("未知错误:", e)
输出:
值错误: 不能为负数
2.10.2.3 捕获所有异常:except Exception
except Exception可以捕获所有类型的异常。
代码演示:
try:
x = 1 / 0
except Exception as e:
print("异常:", e)
输出:
异常: division by zero
2.10.2.4 获取异常信息:as 关键字
as关键字用于获取异常的实例。
代码演示:
try:
x = 1 / 0
except ZeroDivisionError as e:
print("异常信息:", e)
输出:
异常信息: division by zero
2.10.3 else 子句
2.10.3.1 异常未发生时执行的代码
else子句中的代码仅在try块没有发生任何异常时执行。
代码演示:
try:
x = 1 / 1
print("尝试执行成功")
except ZeroDivisionError:
print("异常发生")
else:
print("没有异常发生")
输出:
尝试执行成功
没有异常发生
2.10.3.2 try-except-else 的完整结构
try-except-else提供了完整的异常处理结构。
代码演示:
try:
# 尝试执行的代码
pass
except:
# 发生异常时执行的代码
pass
else:
# 没有异常发生时执行的代码
pass
输出:
# 根据代码执行情况输出
2.10.4 finally 子句
2.10.4.1 保证资源释放的场景
finally子句用于确保资源被释放,无论是否发生异常。
代码演示:
try:
f = open("file.txt", "w")
f.write("Hello")
except:
print("发生异常")
finally:
f.close()
print("文件已关闭")
输出:
文件已关闭
2.10.4.2 try-except-finally 的组合使用
try-except-finally提供了完整的异常处理和资源管理结构。
代码演示:
try:
# 尝试执行的代码
pass
except:
# 发生异常时执行的代码
pass
else:
# 没有异常发生时执行的代码
pass
finally:
# 总是执行的代码
pass
输出:
# 根据代码执行情况输出
2.10.4.3 finally 和异常传播的关系
即使finally块执行,异常仍然会传播。
代码演示:
try:
1 / 0
except:
print("捕获异常")
finally:
print("执行 finally")
输出:
捕获异常
执行 finally
2.10.5 抛出异常
2.10.5.1 使用 raise 抛出异常
raise关键字用于抛出指定的异常。
代码演示:
x = -1
if x < 0:
raise ValueError("不能为负数")
输出:
Traceback (most recent call last):
...
ValueError: 不能为负数
2.10.5.2 重新抛出捕获的异常
可以在except块中重新抛出异常。
代码演示:
try:
x = 1 / 0
except ZeroDivisionError as e:
print("捕获异常")
raise e
输出:
捕获异常
Traceback (most recent call last):
...
division by zero
2.10.6 自定义异常
2.10.6.1 创建自定义异常类
可以通过继承Exception类来创建自定义异常。
代码演示:
class MyError(Exception):
pass
try:
raise MyError("自定义异常")
except MyError as e:
print("捕获自定义异常:", e)
输出:
捕获自定义异常: 自定义异常
2.10.6.2 自定义异常的使用场景
自定义异常可以在需要特定错误处理逻辑时使用。
代码演示:
class NegativeNumberError(Exception):
pass
def process_number(num):
if num < 0:
raise NegativeNumberError("不能为负数")
print("处理数字:", num)
try:
process_number(-1)
except NegativeNumberError as e:
print("错误:", e)
输出:
错误: 不能为负数
2.10.6.3 自定义异常和内置异常的组合使用
自定义异常可以与内置异常结合使用。
代码演示:
class MyValueError(ValueError):
pass
try:
raise MyValueError("自定义值错误")
except ValueError as e:
print("捕获值错误:", e)
输出:
捕获值错误: 自定义值错误
2.10.7 异常的嵌套处理
2.10.7.1 嵌套的 try-except 结构
try-except结构可以嵌套使用。
代码演示:
try:
try:
x = 1 / 0
except ZeroDivisionError:
print("内部异常")
raise
except Exception as e:
print("外部异常:", e)
输出:
内部异常
外部异常: division by zero
2.10.7.2 处理复杂逻辑中的异常
在复杂逻辑中,嵌套的异常处理可以帮助精确捕获和处理异常。
代码演示:
try:
# 外层逻辑
try:
# 内层逻辑
x = 1 / 0
except ZeroDivisionError:
print("处理内部除零错误")
except Exception as e:
print("处理外部异常:", e)
输出:
处理内部除零错误
处理外部异常: division by zero
2.10.8 上下文管理与异常
2.10.8.1 上下文管理的基本概念
上下文管理器允许代码在进入和退出上下文时执行特定的操作。
2.10.8.2 使用 with 语句管理资源
with语句用于管理资源,如文件操作。
代码演示:
with open("file.txt", "w") as f:
f.write("Hello")
输出:
# 文件 file.txt 内容为: Hello
2.10.8.3 自定义上下文管理器的异常处理
自定义上下文管理器可以在__enter__和__exit__方法中处理异常
。
代码演示:
class MyContextManager:
def __enter__(self):
print("进入上下文")
return self
def __exit__(self, exc_type, exc_value, traceback):
print("退出上下文")
if exc_type:
print("处理异常:", exc_value)
with MyContextManager() as manager:
x = 1 / 0
输出:
进入上下文
退出上下文
处理异常: division by zero
2.10.9 异常处理的最佳实践
2.10.9.1 捕获具体的异常类型
应该捕获具体的异常类型,而不是捕获所有异常。
代码演示:
try:
x = int(input("请输入一个整数: "))
except ValueError:
print("请输入一个有效的整数")
输出:
请输入一个有效的整数
2.10.9.2 避免滥用 except Exception
避免捕获所有异常,因为这可能会隐藏真正的错误。
代码演示:
try:
x = 1 / 0
except Exception:
print("捕获所有异常")
输出:
捕获所有异常
2.10.9.3 记录和调试异常
应该记录异常信息以便于调试。
代码演示:
try:
x = 1 / 0
except Exception as e:
print("异常:", e)
输出:
异常: division by zero
2.10.9.4 使用日志系统记录异常
可以使用日志系统来记录异常信息。
代码演示:
import logging
logging.basicConfig(level=logging.ERROR)
try:
x = 1 / 0
except ZeroDivisionError as e:
logging.error("除零错误: %s", e)
输出:
ERROR:root:除零错误: division by zero
以上是2.10节“异常处理”的内容,包括异常的概念、try-except语句、else和finally子句、抛出异常、自定义异常、异常的嵌套处理、上下文管理与异常以及异常处理的最佳实践。