Python自定义异常案例如何编写异常

wen python案例 26

本文目录导读:

Python自定义异常案例如何编写异常

  1. 基础自定义异常
  2. 带额外信息的异常
  3. 业务逻辑异常
  4. 异常层次结构
  5. 带错误码的异常
  6. 实际应用:文件处理系统

我来通过几个实际案例详细说明Python自定义异常的编写方法。

基础自定义异常

class CustomError(Exception):
    """自定义异常基类"""
    pass
# 使用示例
try:
    raise CustomError("这是自定义异常")
except CustomError as e:
    print(f"捕获到异常: {e}")

带额外信息的异常

class ValidationError(Exception):
    """数据验证异常"""
    def __init__(self, message, field_name, field_value):
        self.field_name = field_name
        self.field_value = field_value
        self.message = message
        super().__init__(self.message)
    def __str__(self):
        return f"{self.message} (字段: {self.field_name}, 值: {self.field_value})"
# 使用示例
def validate_age(age):
    if age < 0 or age > 150:
        raise ValidationError(
            "年龄超出有效范围", 
            "age", 
            age
        )
    return age
try:
    validate_age(-5)
except ValidationError as e:
    print(f"错误信息: {e}")
    print(f"问题字段: {e.field_name}")
    print(f"问题值: {e.field_value}")

业务逻辑异常

class BankAccount:
    class InsufficientBalanceError(Exception):
        """余额不足异常"""
        def __init__(self, account_id, current_balance, required_amount):
            self.account_id = account_id
            self.current_balance = current_balance
            self.required_amount = required_amount
            self.deficit = required_amount - current_balance
            super().__init__(f"账户{account_id}余额不足")
    class FrozenAccountError(Exception):
        """账户冻结异常"""
        def __init__(self, account_id):
            self.account_id = account_id
            super().__init__(f"账户{account_id}已被冻结")
    def __init__(self, account_id, balance=0):
        self.account_id = account_id
        self.balance = balance
        self.frozen = False
    def withdraw(self, amount):
        if self.frozen:
            raise self.FrozenAccountError(self.account_id)
        if amount > self.balance:
            raise self.InsufficientBalanceError(
                self.account_id, 
                self.balance, 
                amount
            )
        self.balance -= amount
        return amount
# 使用示例
account = BankAccount("ACC001", 1000)
try:
    account.withdraw(2000)
except BankAccount.InsufficientBalanceError as e:
    print(f"账户: {e.account_id}")
    print(f"当前余额: {e.current_balance}")
    print(f"需要金额: {e.required_amount}")
    print(f"差额: {e.deficit}元")

异常层次结构

class DatabaseError(Exception):
    """数据库基础异常"""
    pass
class ConnectionError(DatabaseError):
    """连接异常"""
    def __init__(self, host, port, message="数据库连接失败"):
        self.host = host
        self.port = port
        super().__init__(f"{message}: {host}:{port}")
class QueryError(DatabaseError):
    """查询异常"""
    def __init__(self, sql, message="SQL查询错误"):
        self.sql = sql
        super().__init__(f"{message}: {sql}")
class DataConstraintError(DatabaseError):
    """数据约束异常"""
    def __init__(self, field, value, constraint="唯一约束"):
        self.field = field
        self.value = value
        super().__init__(f"{constraint}违反: {field}={value}")
# 使用示例
class DatabaseOperations:
    def execute_query(self, sql, data=None):
        # 模拟数据库操作
        if "INSERT" in sql and data:
            if data.get("username") == "admin":
                raise DataConstraintError("username", "admin")
        if not sql:
            raise QueryError(sql, "SQL语句不能为空")
        return "查询成功"
# 异常处理
def handle_database_operation():
    db = DatabaseOperations()
    try:
        # 尝试插入数据
        db.execute_query("INSERT INTO users", {"username": "admin"})
    except DataConstraintError as e:
        print(f"数据约束错误: {e}")
        # 执行回滚等操作
    except QueryError as e:
        print(f"查询错误: {e}")
    except DatabaseError as e:
        print(f"数据库错误: {e}")

带错误码的异常

class AppError(Exception):
    """应用错误基类"""
    def __init__(self, message, error_code="UNKNOWN"):
        self.error_code = error_code
        self.message = message
        super().__init__(self.message)
class UserNotFoundError(AppError):
    def __init__(self, user_id):
        super().__init__(f"用户 {user_id} 不存在", "USER_NOT_FOUND")
class PermissionDeniedError(AppError):
    def __init__(self, user_id, resource):
        super().__init__(
            f"用户 {user_id} 没有 {resource} 的访问权限", 
            "PERMISSION_DENIED"
        )
class RateLimitError(AppError):
    def __init__(self, retry_after=60):
        self.retry_after = retry_after
        super().__init__(
            f"请求过于频繁,请在 {retry_after} 秒后重试",
            "RATE_LIMIT"
        )
# 使用示例
def get_user_data(user_id, requester_id):
    try:
        # 模拟业务逻辑
        if user_id == "999":
            raise UserNotFoundError(user_id)
        if requester_id != "admin":
            raise PermissionDeniedError(requester_id, "user_data")
    except AppError as e:
        # 统一的错误处理
        error_response = {
            "error_code": e.error_code,
            "message": e.message,
            "timestamp": "2024-01-01 12:00:00"
        }
        if isinstance(e, RateLimitError):
            error_response["retry_after"] = e.retry_after
        return error_response
# 测试
print(get_user_data("999", "user1"))
print(get_user_data("123", "user1"))

实际应用:文件处理系统

import os
from datetime import datetime
class FileSystemError(Exception):
    """文件系统基础异常"""
    def __init__(self, filepath, message):
        self.filepath = filepath
        self.timestamp = datetime.now()
        super().__init__(f"[{self.timestamp}] {message}: {filepath}")
class FileNotFound(FileSystemError):
    def __init__(self, filepath):
        super().__init__(filepath, "文件不存在")
class FilePermissionError(FileSystemError):
    def __init__(self, filepath, operation):
        super().__init__(filepath, f"没有 {operation} 权限")
class FileSizeError(FileSystemError):
    def __init__(self, filepath, current_size, max_size):
        self.current_size = current_size
        self.max_size = max_size
        super().__init__(filepath, f"文件过大: {current_size} > {max_size}")
class FileManager:
    def __init__(self):
        self.max_file_size = 1024 * 1024  # 1MB
    def read_file(self, filepath):
        if not os.path.exists(filepath):
            raise FileNotFound(filepath)
        if not os.access(filepath, os.R_OK):
            raise FilePermissionError(filepath, "读取")
        size = os.path.getsize(filepath)
        if size > self.max_file_size:
            raise FileSizeError(filepath, size, self.max_file_size)
        with open(filepath, 'r') as f:
            return f.read()
# 使用示例
def process_file(filepath):
    manager = FileManager()
    try:
        content = manager.read_file(filepath)
        print(f"文件读取成功,内容长度: {len(content)}")
    except FileNotFound as e:
        print(f"错误: {e}")
        print(f"文件路径: {e.filepath}")
    except FilePermissionError as e:
        print(f"权限错误: {e}")
        print(f"操作: 读取")
    except FileSizeError as e:
        print(f"文件过大: {e}")
        print(f"当前大小: {e.current_size} bytes")
        print(f"最大限制: {e.max_size} bytes")
    except FileSystemError as e:
        print(f"文件系统错误: {e}")
    except Exception as e:
        print(f"未知错误: {e}")
# 1. 异常命名规范
class MyCustomError(Exception):
    """使用Error结尾,清晰表达异常类型"""
    pass
# 2. 保持异常层次结构
class BaseAppError(Exception): pass
class SpecificError(BaseAppError): pass
# 3. 提供有意义的错误信息
class MeaningfulError(Exception):
    def __init__(self, message, context=None):
        self.context = context or {}
        super().__init__(message)
# 4. 异常中携带必要数据
class DataError(Exception):
    def __init__(self, message, data=None):
        self.data = data
        super().__init__(message)
# 5. 使用文档字符串说明异常场景
class TimeoutError(Exception):
    """当操作超时时抛出
    Attributes:
        timeout: 超时时间(秒)
        operation: 超时操作描述
    """
    def __init__(self, timeout, operation):
        self.timeout = timeout
        self.operation = operation
        super().__init__(f"操作 '{operation}' 超时 ({timeout}秒)")

这些示例涵盖了自定义异常的主要用法,可以根据实际需求选择和调整。

抱歉,评论功能暂时关闭!