本文目录导读:

我来通过几个实际案例详细说明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}秒)")
这些示例涵盖了自定义异常的主要用法,可以根据实际需求选择和调整。