2016-12-13 5 views
3

特定の条件が満たされたときに、強制的に早期に終了することができるコンテキストマネージャーを作成する必要があります。python3コンテキストマネージャー早期終了強制

詳細:

コンテキストマネージャは、リソースを解放/ロック/チェック処理する必要があります。 __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.") 

上記のコード__enter____exit__内部の呼び出しが実行されてからのコンテキスト内のコードを停止していないため、実際には、しかし、動作しません。

また、__enter__からResourceLockedExceptionをスローすることもできますが、__exit__は呼び出されません。これは、コンテキストマネージャ自体から例外がスローされるためです。私は例外をキャッチし、警告を記録し、リソースがロックされている場合はコンテキストを入力できないようにしたいと思います。

これはコンテキストを早期にクローズする方法を見つけることになるため、__exit__が呼び出され、コンテキストコードは実行されません。上記のどちらかの方法でこれを調整する方法はありますか?それとも別の方法がありますか?

答えて

0

はい、このように手動で__exit__を呼び出すことはできません。 1つの他の選択肢は、単にraise例外であり、別の構成でそれを管理させるものです。あなたはtry-exceptを使用するか、これらのログを記録するために、別のコンテキストマネージャをかき立てることができ、次のいずれか

from contextlib import 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句を代わりに使用することもできます。

関連する問題