如何创建仅支持单次使用的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
相关产品推荐
相关产品推荐

