web-dev-qa-db-ja.com

Pythonでnull(no-op)コンテキストマネージャーを記述する方法

時々、何もしないダミーのコンテキストマネージャーが必要です。その後、より便利ですがオプションのコンテキストマネージャーの代用として使用できます。例えば:

ctx_mgr = <meaningfulContextManager> if <condition> else <nullContextManager>
with ctx_mgr:
    ...

このような些細な空のコンテキストマネージャを定義するにはどうすればよいですか? Pythonライブラリは既製のものを提供しますか?

as句でコンテキストを使用したい場合はどうですか?

with ctx_mgr as resource:
    <operations on resource>
29
Julian

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よりも遅いですが(テストでは2倍の時間がかかります)。

Before Python 3.3)、またはasPython 3.7、開発者は独自に展開する必要があります。以下に実装例を示します。 :

_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__()の意味のあるコンテキストマネージャーが、マネージブロック内のquack()に対して行われた何かを返す場合、_dummy_resource_もサポートする必要があります。おそらく何もせずに。

_class DummyDuck(object):
    def quack()
        # Ssssh...
        pass

ctx_mgr = <meaningfulContextManager> if <condition> else NullContextManager(DummyDuck())

with ctx_mgr as someDuck:
    someDuck.quack()
_

出典: A Python機能リクエスト 。その議論に貢献してくれたすべての人に感謝します。これは、自己回答の質問でその結果を要約する私の試みです。長いスレッドを読む時間を節約してください。また、Pythonドキュメントの このExitStackの使用 を参照してください。

36
Julian

Python 3.6以下、2.7を含む)の簡単なソリューション:

from contextlib import contextmanager

@contextmanager
def nullcontext(enter_result=None):
    yield enter_result

Python 3.7なので、提供されている contextlib.nullcontext 代わりに。

3
Martin Valgur

Python 3.2、memoryview(b'')はno-opコンテキストマネージャとして使用できます。 https://docs.python.org/3/library/ stdtypes.html#memoryview.release

長所

  • インポート不要

  • 3.2以降で動作します

  • contextlib.nullcontextの約2倍の速度

短所

  • おそらく# no-opコメントを追加する必要があります。
1
Huazuo Gao