当前位置:首页>python>Python学习--自定义异常类详解

Python学习--自定义异常类详解

  • 2026-10-11 08:13:54
Python学习--自定义异常类详解

一、为什么需要自定义异常?

自定义异常可以让你的代码更清晰地表达特定的错误情况,提供更有意义的错误信息,并实现更精细的错误处理。

二、基础自定义异常

1. 最简单的自定义异常

# 最简单的自定义异常class MyError(Exception):    """我的自定义异常"""    pass# 使用示例def test_simple_error():    try:        raise MyError("发生了一个错误")    except MyError as e:        print(f"捕获到自定义异常: {e}")test_simple_error()

2. 带初始化的自定义异常

class ValidationError(Exception):    """验证错误异常"""    def __init__(self, message, field_name=None, code=None):        self.field_name = field_name        self.code = code        # 调用父类构造函数        super().__init__(message)# 使用示例def validate_user(name, age):    if not name:        raise ValidationError("姓名不能为空", field_name="name", code="REQUIRED")    if age < 0:        raise ValidationError("年龄不能为负数", field_name="age", code="INVALID_RANGE")    if age > 150:        raise ValidationError("年龄超出范围", field_name="age", code="OUT_OF_RANGE")try:    validate_user("", 25)except ValidationError as e:    print(f"错误: {e}")    print(f"字段: {e.field_name}")    print(f"错误码: {e.code}")

三、自定义异常的层次结构

1. 创建异常层次

# 定义异常层次class AppError(Exception):    """应用基础异常"""    passclass DatabaseError(AppError):    """数据库错误"""    passclass ConnectionError(DatabaseError):    """连接错误"""    passclass QueryError(DatabaseError):    """查询错误"""    passclass BusinessError(AppError):    """业务逻辑错误"""    passclass ValidationError(BusinessError):    """验证错误"""    passclass AuthorizationError(BusinessError):    """授权错误"""    pass# 使用示例def test_hierarchy():    def db_operation():        raise ConnectionError("无法连接到数据库")    def business_logic():        raise ValidationError("数据验证失败")    try:        db_operation()    except ConnectionError as e:        print(f"连接错误: {e}")    except DatabaseError as e:        print(f"数据库错误: {e}")    except AppError as e:        print(f"应用错误: {e}")    try:        business_logic()    except ValidationError as e:        print(f"验证错误: {e}")    except BusinessError as e:        print(f"业务错误: {e}")test_hierarchy()

2. 多级异常处理

class APIError(Exception):    """API 错误基类"""    passclass ClientError(APIError):    """客户端错误 (4xx)"""    def __init__(self, message, status_code=400):        self.status_code = status_code        super().__init__(message)class ServerError(APIError):    """服务器错误 (5xx)"""    def __init__(self, message, status_code=500):        self.status_code = status_code        super().__init__(message)class NotFoundError(ClientError):    """资源不存在 (404)"""    def __init__(self, resource, resource_id):        self.resource = resource        self.resource_id = resource_id        message = f"{resource} 不存在: {resource_id}"        super().__init__(message, status_code=404)class UnauthorizedError(ClientError):    """未授权错误 (401)"""    def __init__(self, message="需要认证"):        super().__init__(message, status_code=401)# 使用示例def test_api_errors():    def get_user(user_id):        if user_id == 0:            raise UnauthorizedError()        if user_id != 123:            raise NotFoundError("User", user_id)        return {"id": user_id, "name": "Alice"}    user_ids = [0, 999, 123]    for user_id in user_ids:        try:            user = get_user(user_id)            print(f"获取用户成功: {user}")        except UnauthorizedError as e:            print(f"认证错误 ({e.status_code}): {e}")        except NotFoundError as e:            print(f"未找到 ({e.status_code}): {e}")        except ClientError as e:            print(f"客户端错误 ({e.status_code}): {e}")        except APIError as e:            print(f"API错误: {e}")test_api_errors()

四、最佳实践

1. 异常设计原则

class ExceptionDesignPrinciples:    """异常设计原则"""    # 1. 继承自 Exception 而不是 BaseException    class GoodException(Exception):        pass    # 2. 提供有意义的错误信息    class UserNotFoundError(Exception):        def __init__(self, user_id):            super().__init__(f"用户不存在: {user_id}")            self.user_id = user_id    # 3. 保持异常层次合理    class AppError(Exception):        pass    class DatabaseError(AppError):        pass    class ValidationError(AppError):        pass    # 4. 不要滥用自定义异常    # 如果内置异常足够,优先使用内置异常    # 5. 文档化异常    def divide(a, b):        """        除法运算        Raises:            ZeroDivisionError: 当除数为0时            TypeError: 当参数不是数字时        """        return a / b    # 6. 异常应该是可序列化的    class SerializableError(Exception):        def __init__(self, message, code=None):            super().__init__(message)            self.code = code        def to_dict(self):            return {                'type': self.__class__.__name__,                'message': str(self),                'code': self.code            }    print("异常设计原则演示完成")

2. 自定义异常模板

class ExceptionTemplate:    """自定义异常模板"""    # 模板1: 简单异常    class SimpleError(Exception):        """简单错误"""        pass    # 模板2: 带数据的异常    class DataError(Exception):        def __init__(self, message, **kwargs):            self.data = kwargs            super().__init__(message)        def __str__(self):            if self.data:                return f"{super().__str__()}{self.data}"            return super().__str__()    # 模板3: 错误码异常    class CodeError(Exception):        def __init__(self, message, code=500):            self.code = code            super().__init__(f"[{code}] {message}")    # 模板4: 异常链异常    class ChainedError(Exception):        def __init__(self, message, cause=None):            self.cause = cause            if cause:                message = f"{message} (cause: {cause})"            super().__init__(message)    # 模板5: 上下文异常    class ContextError(Exception):        def __init__(self, message, context=None):            self.context = context or {}            super().__init__(message)        def with_context(self, key, value):            self.context[key] = value            return self# 使用模板def test_templates():    try:        raise ExceptionTemplate.SimpleError("简单错误")    except ExceptionTemplate.SimpleError as e:        print(f"简单异常: {e}")    try:        raise ExceptionTemplate.DataError("数据错误", user_id=123, action="delete")    except ExceptionTemplate.DataError as e:        print(f"数据异常: {e}")    try:        raise ExceptionTemplate.CodeError("权限不足", code=403)    except ExceptionTemplate.CodeError as e:        print(f"错误码异常: {e}")    try:        try:            raise ValueError("原始错误")        except ValueError as e:            raise ExceptionTemplate.ChainedError("包装后的错误", cause=e)    except ExceptionTemplate.ChainedError as e:        print(f"链式异常: {e}")test_templates()

五、总结

自定义异常要点表格

 要点
说明
 继承基类
通常继承 Exception,不要继承 BaseException
 构造函数
调用 super().__init__() 传递错误消息
 额外属性
可以添加自定义属性存储额外信息
 异常层次
建立合理的异常层次结构
 文档化
在文档中说明可能抛出的异常

最佳实践总结

  1. 命名规范:异常类名应以 Error 结尾

  2. 继承关系:创建合理的异常层次结构

  3. 提供信息:包含足够的调试信息

  4. 文档化:说明异常的触发条件

  5. 不要滥用:优先使用内置异常

  6. 可序列化:便于日志和传输

自定义异常是 Python 编程中的重要技巧,合理使用可以让代码更清晰、更易维护。通过创建有意义的异常层次和提供丰富的错误信息,可以大大提高程序的健壮性和可调试性。

最新文章

随机文章