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

如何创建仅支持单次使用的Python上下文管理器类

如何创建单次使用的Python上下文管理器

根据Python官方文档描述:

大多数上下文管理器被设计为仅能在with语句中有效使用一次。这类单次使用的上下文管理器每次使用都必须重新创建——尝试第二次使用会触发异常或无法正常工作。
这种常见限制意味着,通常建议在使用上下文管理器的with语句头部直接创建它们(如上述所有使用示例所示)。

但官方给出的基于ContextDecorator的上下文管理器示例却是可重复使用的:

from contextlib import ContextDecorator
import logging

logging.basicConfig(level=logging.INFO)

class track_entry_and_exit(ContextDecorator):
    def __init__(self, name):
        self.name = name

    def __enter__(self):
        logging.info('Entering: %s', self.name)

    def __exit__(self, exc_type, exc, exc_tb):
        logging.info('Exiting: %s', self.name)

实例化后可以多次用于with语句:

test_context = track_entry_and_exit('test')

with test_context:
    pass
# 输出:INFO:root:Entering: test
#      INFO:root:Exiting: test

with test_context:
    pass
# 输出:INFO:root:Entering: test
#      INFO:root:Exiting: test

要实现一个第二次调用with就失败的上下文管理器,只需在类中添加状态标记跟踪使用情况,在__enter__方法中做校验:

from contextlib import ContextDecorator
import logging

logging.basicConfig(level=logging.INFO)

class SingleUseContext(ContextDecorator):
    def __init__(self, name):
        self.name = name
        self._used = False  # 标记是否已被使用

    def __enter__(self):
        if self._used:
            raise RuntimeError("该上下文管理器只能使用一次")
        self._used = True
        logging.info('Entering: %s', self.name)

    def __exit__(self, exc_type, exc, exc_tb):
        logging.info('Exiting: %s', self.name)

测试效果:

test_context = SingleUseContext('test')

# 第一次使用正常执行
with test_context:
    pass
# 输出:INFO:root:Entering: test
#      INFO:root:Exiting: test

# 第二次使用直接抛出异常
with test_context:
    pass
# 触发异常:RuntimeError: 该上下文管理器只能使用一次

核心逻辑是通过_used属性记录上下文管理器的使用状态,每次进入with块时先校验状态,已使用则抛出异常,未使用则标记为已使用。

内容的提问来源于stack exchange,提问作者Andrés Marafioti

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 21:55:21