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__을 호출 할 수 없습니다. 또 다른 대안은 단순히 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 절을 번갈아 사용할 수도 있습니다.