12.异常处理

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.
相关推荐
HsuHeinrich2 分钟前
流程图(四)利用python绘制漏斗图
python·数据可视化
吾当每日三饮五升34 分钟前
C++单例模式跨DLL调用问题梳理
开发语言·c++·单例模式
猫武士水星1 小时前
C++ scanf
开发语言·c++
BinaryBardC2 小时前
Bash语言的数据类型
开发语言·后端·golang
码农丁丁2 小时前
[python3]Excel解析库-xlwt
python·excel·xlwt
Lang_xi_2 小时前
Bash Shell的操作环境
linux·开发语言·bash
reasonsummer2 小时前
【办公类-47-02】20250103 课题资料快速打印(单个docx转PDF,多个pdf合并一个PDF 打印)
python·pdf
Pandaconda2 小时前
【Golang 面试题】每日 3 题(二十一)
开发语言·笔记·后端·面试·职场和发展·golang·go
捕鲸叉2 小时前
QT自定义工具条渐变背景颜色一例
开发语言·前端·c++·qt
想要入门的程序猿2 小时前
Qt菜单栏、工具栏、状态栏(右键)
开发语言·数据库·qt