1.什么是异常
2.异常的基本结构
- try和except
- 捕获多个异常
- else块
- finally块
3.raise关键字
- 基本用法
- 引发特定异常
- raise from的用法
4.assert语句
5.自定义异常
- 创建自定义异常类
- 使用自定义异常
- 案例
1. 什么是异常?
- 异常是程序运行时发生的错误事件,可能导致程序终止。
- 异常可以由程序错误(如除以零、访问不存在的变量)或外部条件(如文件未找到、网络连接失败)引发。
2. 异常的基本结构
Python 使用 try、except、else 和 finally 关键字来处理异常。
2.1 try 和 except
- try 块包含可能引发异常的代码。
- except 块用于捕获和处理异常。
python
try:
result = 10 / 0
except ZeroDivisionError as e:
print(f"Error: {e}") # 输出: Error: division by zero
说明:
- try 块:包含可能会引发异常的代码。在这个例子中,我们尝试将 10 除以 0,这会引发 ZeroDivisionError,因为除以零是未定义的。
- except 块:捕获特定的异常类型。在这里,我们捕获 ZeroDivisionError 并将其存储在变量 e 中,然后打印错误信息。
2.2 捕获多个异常
- 可以在一个 try 块中捕获多个异常。
python
try:
result = 10 / 0
except (ZeroDivisionError, ValueError) as e:
print(f"Error: {e}")
说明:这个例子展示了如何捕获多个异常类型。虽然在这个特定的代码中只会引发 ZeroDivisionError,但如果有其他代码可能引发 ValueError,它也会被捕获。
2.3 else 块
- else 块在 try 块没有引发异常时执行。
python
try:
result = 10 / 2
except ZeroDivisionError:
print("Cannot divide by zero")
else:
print(f"Result is {result}") # 输出: Result is 5.0
说明:else 块:在 try 块没有引发异常时执行。在这个例子中,10 除以 2 是有效的操作,所以 else 块会执行并打印结果。
2.4 finally 块
- finally 块无论是否发生异常都会执行,通常用于清理资源。
python
try:
file = open('example.txt', 'r')
# 进行文件操作
except FileNotFoundError:
print("File not found")
finally:
file.close() # 确保文件被关闭
说明:finally 块:无论是否发生异常,finally 块中的代码都会执行。这里用于确保文件在操作后被关闭,即使在打开文件时发生了异常。
3.raise关键字
3.1基本用法
raise 关键字可以用来引发一个指定的异常。最简单的形式是直接引发一个异常实例:
python
raise Exception("This is an error message") #爆红,输出:Exception: This is an error message
解释:
- 这行代码会立即引发一个 Exception,并附带一个错误消息 "This is an error message"。
- 如果没有捕获这个异常,程序会终止,并显示错误信息。
3.2引发特定异常
Python 提供了许多内置异常类,如 ValueError、TypeError、IndexError 等。你可以使用 raise 来引发这些特定的异常:
python
def divide(x, y):
if y == 0:
raise ZeroDivisionError("Cannot divide by zero")
return x / y
try:
divide(10, 0)
except ZeroDivisionError as e:
print(e) # 输出: Cannot divide by zero
解释:
- 在 divide 函数中,如果 y 为零,raise 会引发 ZeroDivisionError。
- 在 try 块中调用 divide,并在 except 块中捕获并处理该异常。
3.3raise from的用法
raise ... from ... 语法用于在引发一个新的异常时,保留原始异常的信息。这样做的好处是,当你处理异常时,可以看到新异常和原始异常之间的关系。
python
try:
# 可能引发异常的代码
raise KeyError("Original exception")
except KeyError as e:
# 引发新的异常,并指定原始异常为其原因
raise ValueError("New exception") from e
解释:
- ValueError("New exception") 是新引发的异常。
- from e 指定 e(即 KeyError("Original exception"))为新异常的原因。
- 这会创建一个异常链,使得 ValueError 的 cause 属性指向 KeyError。
python
def read_file(file_path):
try:
with open(file_path, 'r') as file:
return file.read()
except FileNotFoundError as e:
raise RuntimeError("Failed to read the file") from e
try:
content = read_file("non_existent_file.txt")
except RuntimeError as e:
print(f"Caught an exception: {e}")
print(f"Original cause: {e.__cause__}")
#输出:
#Caught an exception: Failed to read the file
#Original cause: [Errno 2] No such file or directory: 'non_existent_file.txt'
说明:
- read_file 函数尝试打开并读取一个文件。
- 如果文件不存在,会引发 FileNotFoundError。
- 在 except 块中,raise RuntimeError("Failed to read the file") from e 引发一个新的 RuntimeError,并将 FileNotFoundError 作为其原因。
- 在外部 try 块中捕获 RuntimeError,并通过 e.cause 访问原始异常。
4.assert语句
assert 语句:用于调试时检查条件是否为真。如果条件为假,assert 会引发 AssertionError。在这个例子中,x 是正数,所以不会引发异常。
python
x = 10
assert x > 0, "x must be positive"
5.自定义异常
5.1创建自定义异常类
- 继承 Exception 类。
- 通常,重写 init 方法以接受自定义的错误信息。
python
class MyCustomError(Exception):
def __init__(self, message):
super().__init__(message)
self.message = message
5.2使用自定义异常
- 在代码中使用 raise 关键字引发自定义异常。
- 使用 try 和 except 块捕获并处理自定义异常。
python
class MyCustomError(Exception):
def __init__(self, message):
super().__init__(message)
self.message = message
def check_positive(number):
if number < 0:
raise MyCustomError("Number must be positive")
try:
check_positive(-1)
except MyCustomError as e:
print(f"Caught an exception: {e.message}") #输出:Caught an exception: Number must be positive
5.3案例
假设我们正在开发一个银行系统,需要处理账户余额不足的情况。我们可以创建一个自定义异常 InsufficientFundsError 来处理这种情况。
python
class InsufficientFundsError(Exception):
def __init__(self, balance, amount):
message = f"Attempted to withdraw {amount}, but only {balance} is available."
super().__init__(message)
self.balance = balance
self.amount = amount
class BankAccount:
def __init__(self, balance):
self.balance = balance
def withdraw(self, amount):
if amount > self.balance:
raise InsufficientFundsError(self.balance, amount)
self.balance -= amount
return self.balance
# 使用示例
account = BankAccount(100)
try:
account.withdraw(150)
except InsufficientFundsError as e:
print(e) # 输出: Attempted to withdraw 150, but only 100 is available.