2017-07-19 18 views
4

時々、何もしないダミーのコンテキストマネージャが必要です。それは、より有用な、しかしオプションのコンテキストマネージャーのためのスタンドインとして使用することができます。例:Pythonでヌル(無操作)コンテキストマネージャを作成するにはどうすればよいですか?

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

このような単純で空のコンテキストマネージャーを定義するにはどうすればよいですか? Pythonライブラリは1つをシェルフから提供していますか?

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

with ctx_mgr as resource: 
    <operations on resource> 
+1

「あれと何か:」の代わりに 'もし1:'はどうですか? – Alfe

答えて

9

速報:Pythonの3.7は、このような理由(commit)のために特別にnullcontextを提供します。私は利用可能な場合は、ドキュメントへのリンクを更新します。

3.7より前のPythonバージョン:標準ライブラリでは、これらのユースケース用に特別に設計されたコンテキストマネージャは提供されていません。

しかし、それはas句が存在しない場合(バージョン3.4以降で利用可能)contextlib.suppress、すなわち、最初のケースでは、その目的のために使用できることが判明:

ctx_mgr = <meaningfulContextManager> if <condition> else contextlib.suppress() 

with ctx_mgr: 
    ... 

のPython 3.3、同様の作業ためまた、よりも遅いですが、contextlib.ExitStack(テストでは2倍の時間がかかります)も利用できます。

as句が必要な場合や、3.3より古いPythonバージョンを使用している場合は、開発者が独自にロールバックする必要があります。ここ は、一つの可能​​な実装は(下のメモを参照しますが、すべてのエラーは私のもの)である。もちろん、

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

with ctx_mgr as resource: 
    <operations on resource> 

dummy_resourceが必要なすべての操作をサポートする必要があります。

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 

一つは、その後、書くことができます「意味のある」資源のたとえば、意味のあるコンテキストマネージャー__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 feature request。その議論に貢献したすべての人に感謝します。これは、自分の答えた質問でその結果を要約し、長いスレッドを読む時間を節約するための私の試みです。また、Pythonドキュメントのthis use of ExitStackの記述を参照してください。

+1

ドキュメントでは、ExitStackは何もしないコンテキストマネージャとしてここに記載されています。https://docs.python.org/3/library/contextlib.html#simplifying-support-foringle-optional-context-managers – Gribouillis

+0

私は修正済みです - 固定、ありがとう。 – Julian

+1

** UPD 2017年11月23日**最後に 'nullcontext'でコミットがありますhttps://bugs.python.org/issue10049#msg306770 – maxkoryukov

0

私はダミーコンテキストマネージャーとしてthreading.Lock()を使用しました。一時ロック。コンテキストマネージャのみが使用します。

関連する問題