我需要创建一个上下文管理器,当满足某些条件时,可以强制它提前退出。
更多详情:
上下文管理器需要处理检查/锁定/释放资源。在__enter__
上,上下文管理器需要检查资源是否已锁定。如果是,我希望在不执行上下文中的代码的情况下调用__exit__
。否则,上下文管理器获取资源,执行上下文代码,并清除__exit__
中的资源。
它可能看起来像这样:
class my_context_manager:
def __enter__(self):
if resource_locked():
self.__exit__(None, ResourceLockedException(), None)
else:
acquire_resource()
def __exit__(self, *exc_info):
if not isinstance(exc_info[1], ResourceLockedException):
release_resource()
else:
log.warn("Resource already in use.")
上面的代码实际上并不起作用,因为在__exit__
内调用__enter__
并不会阻止上下文中的代码被执行。
或者,我可以从ResourceLockedException
中抛出__enter__
,但后来__exit__
不会被调用,因为异常将从上下文管理器本身抛出。我希望能够捕获异常,记录警告,如果资源被锁定则不输入上下文。
这归结为找到一些早期关闭上下文的方法,以便调用__exit__
并且不执行上下文代码。有没有办法调整上述任何一个想法来做到这一点?或者还有另一种方式吗?
答案 0 :(得分:1)
是的,您无法像这样手动拨打__exit__
。另一种选择只是raise
异常,让另一个构造管理它。您可以使用try-except
或掀起另一个上下文管理器来记录这些:
from contextlib import contextmanager
@contextmanager
def log_exception():
try:
yield
except ResourceLockedException as e:
log.warn(e)
并将原始上下文管理器更改为:
class my_context_manager:
def __enter__(self):
if True:
raise ResourceLockedException("Resource already in use")
acquire_resource()
def __exit__(self):
release_resource()
并将其命名为:
with log_exception(), my_context_manager():
# do things when resource acquired.
当然,您可以在其中使用try-except
并嵌套with
,或者使用if
子句。