python - 如何在 Python 中编写空(无操作)上下文管理器?

标签 python contextmanager

有时我需要一个什么都不做的虚拟上下文管理器。然后它可以用作更有用但可选的上下文管理器的替代品。例如:

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/

相关文章:

运行 mysql 查询时的 Python 'TypeError: not enough arguments for format string'

python - 我声明--> str1 ="bbccaa"。我希望结果是所有 b 和 a,即 'bbaa' ,但是

python - Postgresql更新导致: 'django.db.utils.OperationalError: could not access file "$libdir/postgis-2. 4": No such file or directory'

python - 上下文管理器可以在 Python 中多次运行包含的 block 吗?

多行的 Python 嵌套上下文管理器

python - 我怎样才能在某些条件下获得 numpy 数组索引

python - 运行 Python 脚本从 CNN 抓取新闻报道时没有得到任何输出

python - 没有 Yield 的上下文管理器

python - 将上下文管理器与装饰器混合使用时未捕获到异常

python - 对 Python 中 try 和 with 的正确顺序感到困惑