You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现上下文外调用时抛出异常的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 12:15:39