有时我需要一个什么都不做的虚拟上下文管理器。然后它可以用作更有用但可选的上下文管理器的替代品。例如:
ctx_mgr = <meaningfulContextManager> if <condition> else <nullContextManager>
with ctx_mgr:
...
如何定义这样一个琐碎的、空的上下文管理器? Python 库是否提供现成的库?
我们希望上下文与 as
子句一起使用的情况如何?
with ctx_mgr as resource:
<operations on resource>
最佳答案
Python 3.7 及以上版本:使用 contextlib.nullcontext
,为此专门设计的。
在 Python 3.7 之前,标准库不提供专门为这些用例设计的上下文管理器,但有一些变通方法。
从 Python 3.4 开始,contextlib.suppress
在第一种情况下可以用于该目的,即当没有 as
子句时:
ctx_mgr = <meaningfulContextManager> if <condition> else contextlib.suppress()
with ctx_mgr:
...
从 Python 3.3 开始,也可以使用类似的解决方法,contextlib.ExitStack
,尽管比 suppress
慢(在我的测试中它需要两倍的时间)。
Python 3.3 之前,或如果您需要 Python 3.7 之前的 as
子句,开发人员需要自己推出。
这是一种可能的实现(见底部的注释,但所有错误都是我的):
class NullContextManager(object):
def __init__(self, dummy_resource=None):
self.dummy_resource = dummy_resource
def __enter__(self):
return self.dummy_resource
def __exit__(self, *args):
pass
然后可以写:
ctx_mgr = <meaningfulContextManager> if <condition> else NullContextManager(dummy_resource)
with ctx_mgr as resource:
<operations on resource>
当然,dummy_resource
需要支持“有意义”资源所需的所有操作。因此,例如,如果有意义的上下文管理器,在 __enter__()
上,返回在托管 block dummy_resource
内的 quack()
> 也需要支持这一点,尽管可能根本不做任何事情。
class DummyDuck(object):
def quack()
# Ssssh...
pass
ctx_mgr = <meaningfulContextManager> if <condition> else NullContextManager(DummyDuck())
with ctx_mgr as someDuck:
someDuck.quack()
来源:A Python feature request .非常感谢所有参与讨论的人。这是我在一个 self 回答的问题中总结其结果的尝试,以节省人们阅读该长线程的时间。另请参阅 Python 文档中提到的 this use of ExitStack
。 .
关于python - 如何在 Python 中编写空(无操作)上下文管理器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45187286/