如何实现上下文外调用时抛出异常的Python装饰器?
实现仅允许在上下文管理器内调用方法的数据库接口类
我需要开发一个数据库接口类,要求类中的业务方法只能在with语句的上下文内调用,否则抛出异常。预期使用方式如下:
with DBInterfaceContext() as session: session.do_something1() session.do_something2()
以下是完整的实现代码,补全了基础模板中的缺失部分:
from contextlib import AbstractContextManager from functools import wraps class DBInterfaceContext(AbstractContextManager): """仅允许在上下文内调用方法的数据库接口示例""" def __init__(self, db_url): self.db_url = db_url self._connection = None self._in_session = False def __enter__(self): # 模拟建立数据库连接 print(f"建立与 {self.db_url} 的数据库连接") self._connection = f"DBConnection({self.db_url})" self._in_session = True return self def __exit__(self, exc_type, exc_value, traceback): # 模拟关闭数据库连接 if self._connection: print(f"关闭与 {self.db_url} 的数据库连接") self._connection = None self._in_session = False # 返回False让异常正常传播,返回True则抑制异常 return False def in_session(self): return self._in_session @classmethod def require_session(cls, meth): @wraps(meth) def wrapped_method(self, *args, **kwds): if not self.in_session(): raise RuntimeError(f"方法 {meth.__name__} 必须在会话上下文内调用") return meth(self, *args, **kwds) return wrapped_method @require_session def do_something1(self, data): print(f"执行数据库操作1: {data},使用连接 {self._connection}") @require_session def do_something2(self, id): print(f"执行数据库操作2: 查询ID={id},使用连接 {self._connection}")
关键实现说明
- 继承
AbstractContextManager:简化上下文管理器的实现,无需手动处理部分上下文协议细节 - 会话状态跟踪:通过
_in_session实例变量标记当前是否处于with上下文内 - 装饰器校验:
require_session装饰器会在调用业务方法前检查会话状态,未处于会话中则抛出RuntimeError - 连接生命周期:
__enter__方法负责初始化数据库连接,__exit__方法负责清理连接,确保资源正确释放
内容的提问来源于stack exchange,提问作者BorjaEst
相关产品推荐
相关产品推荐

