十分想念顺店杂可。。。

在 Python 中,异常处理是保证程序健壮性的重要机制,用于捕获和处理程序运行时的错误(如除以零、文件不存在等),避免程序直接崩溃。常用的异常处理方法围绕 tryexceptelsefinally 等关键字展开,以下是详细介绍:

一、基本结构:try-except 块

最基础的异常处理结构,用于捕获并处理指定类型的异常。

语法

try:
    # 可能发生异常的代码块(被监控的代码)
    可能出错的语句
except 异常类型1:
    # 当发生“异常类型1”时执行的处理代码
    处理逻辑1
except 异常类型2:
    # 当发生“异常类型2”时执行的处理代码
    处理逻辑2

示例:捕获除法中的 “除以零” 异常

a = 10
b = 0

try:
    result = a / b  # 这里会触发 ZeroDivisionError
except ZeroDivisionError:
    print("错误:除数不能为零!")  # 捕获到异常时执行

二、捕获多个异常

当代码可能触发多种异常时,可以用多种方式处理:

1. 多个 except 子句(推荐)

针对不同异常类型,编写不同的处理逻辑(更清晰):

try:
    num = int(input("请输入一个整数:"))
    result = 10 / num
except ValueError:
    print("错误:输入的不是有效整数!")
except ZeroDivisionError:
    print("错误:除数不能为零!")
2. 一个 except 捕获多种异常(元组形式)

当多种异常的处理逻辑相同时,可合并捕获:

try:
    num = int(input("请输入一个整数:"))
    result = 10 / num
except (ValueError, ZeroDivisionError) as e:  # as e 获取异常对象
    print(f"发生错误:{e}")  # 打印异常具体信息(如"invalid literal for int() with base 10: 'abc'")

三、捕获所有异常(不推荐,但特殊场景可用)

使用 except Exception 可捕获所有非系统退出类异常(避免用 bare except,即无异常类型的 except):

try:
    # 可能出错的代码
    file = open("nonexistent.txt", "r")
except Exception as e:
    print(f"发生未知错误:{e}")  # 捕获所有非退出异常(如FileNotFoundError)

注意

  • 不建议滥用,会掩盖真正需要解决的错误(如逻辑错误)。
  • 系统退出异常(如 KeyboardInterrupt 即 Ctrl+C)无法被 Exception 捕获。

四、else 子句:无异常时执行

else 可选,当 try 块没有发生任何异常时执行,用于区分 “正常逻辑” 和 “异常处理逻辑”:

try:
    num = int(input("请输入一个正数:"))
    assert num > 0  # 断言:若num<=0则触发AssertionError
except (ValueError, AssertionError) as e:
    print(f"输入错误:{e}")
else:
    # 只有无异常时才执行
    print(f"你输入的正数是:{num}")

五、finally 子句:无论是否异常都执行

finally 可选,无论 try 块是否发生异常,都会执行,常用于释放资源(如关闭文件、网络连接等):

file = None
try:
    file = open("test.txt", "r")
    content = file.read()
except FileNotFoundError:
    print("文件不存在!")
finally:
    # 无论是否异常,都确保文件关闭
    if file is not None:
        file.close()
        print("文件已关闭")

场景:资源释放(文件、数据库连接、锁等),确保资源不会泄露。

六、主动抛出异常:raise 语句

除了捕获系统自动抛出的异常,还可以用 raise 主动抛出指定异常,用于自定义错误检查逻辑。

语法

raise 异常类型(异常信息)

示例:自定义年龄合法性检查

def check_age(age):
    if not isinstance(age, int):
        # 主动抛出“类型错误”
        raise TypeError("年龄必须是整数!")
    if age < 0 or age > 150:
        # 主动抛出“值错误”
        raise ValueError("年龄必须在0-150之间!")
    print(f"年龄合法:{age}")

try:
    check_age("20")  # 触发TypeError
except (TypeError, ValueError) as e:
    print(f"检查失败:{e}")

七、自定义异常类

当系统内置异常(如 ValueError)不足以描述业务错误时,可自定义异常类(需继承 Exception 类)。

示例:自定义 “余额不足” 异常

# 自定义异常(继承自Exception)
class InsufficientFundsError(Exception):
    """自定义异常:表示账户余额不足"""
    def __init__(self, balance, amount):
        self.balance = balance  # 当前余额
        self.amount = amount    # 要支出的金额
        super().__init__(f"余额不足!当前余额:{balance},需支出:{amount}")

# 使用自定义异常
def withdraw(balance, amount):
    if amount > balance:
        # 抛出自定义异常
        raise InsufficientFundsError(balance, amount)
    return balance - amount

try:
    new_balance = withdraw(100, 200)
except InsufficientFundsError as e:
    print(f"取款失败:{e}")  # 输出:取款失败:余额不足!当前余额:100,需支出:200

八、断言:assert 语句(调试用)

assert 用于在调试阶段检查条件是否为真,若为假则抛出 AssertionError,可视为 “简化版的异常触发”。

语法

assert 条件表达式, 异常信息  # 条件为False时触发异常

示例

def calculate_average(scores):
    # 断言:列表不能为空(调试阶段检查)
    assert len(scores) > 0, "分数列表不能为空!"
    return sum(scores) / len(scores)

try:
    avg = calculate_average([])  # 触发AssertionError
except AssertionError as e:
    print(f"计算失败:{e}")

注意

  • 断言主要用于调试,生产环境中可通过 -O 选项关闭(忽略所有断言),因此不能替代正式的异常处理。

异常处理的最佳实践

  1. 捕获具体异常:避免用 except Exception 捕获所有异常,应明确指定需要处理的异常类型(如 FileNotFoundError)。
  2. 不要忽略异常:即使暂时无法处理,也应记录异常信息(如用 logging 模块),避免无声失败。
  3. 释放资源用 finally:文件、网络连接等资源必须确保关闭,finally 是最可靠的方式(或用 with 上下文管理器)。
  4. 自定义异常增强可读性:业务相关的错误用自定义异常,使代码更易理解和维护。

通过合理使用异常处理,可使程序在遇到错误时优雅降级,而非直接崩溃,同时提供清晰的错误信息,便于调试和维护。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐