2016-06-03 7 views
1

Updater라는 장기 실행 프로세스가 있으며이 프로세스에는 업데이트 (ETL 시스템에 대한 업데이트)가 제출되었습니다. 업데이트에는 컨텍스트 관리자를 Updater의 ExitStack에 추가하여 관리되는 리소스 요구 사항이 있습니다. 일부 업데이트에는 새로운 구성이 포함됩니다. 즉, 영향을받는 리소스가 스택에서 릴리스되어야하며 새로 구성된 버전의 리소스가 추가되어야합니다. 다음과 같은 것이 필요합니다.ExitStack에서 컨텍스트 관리자를 제거하는 방법

with ExitStack() as stack: 
    ctx_manager = open("file.txt") 
    f = stack.enter_context(ctx_manager) 
    ... 
    ctx_pop(ctx_manager, stack) # remove the given context manager from the stack 

다음은 내가 작업 한 예이지만 보호 된 멤버에 액세스하는 방법에 의존합니다.

def ctx_pop(cm, stack): 
    for item in stack._exit_callbacks: 
     if item.__self__ is cm: 
      break 
    else: 
     raise KeyError(repr(cm)) 
    stack._exit_callbacks.remove(item) 
    item(None, None, None) 

편집 : 추가 알려진 솔루션

+1

소스 코드를 보면'ExitStack'는 당신이 필요로하는 것, 그래서 컨텍스트'.__ exit__' 방법에 대해 래퍼를 저장하는'deque'를 사용 내가 아는 한 가능하지 않은 원래 컨텍스트 관리자에 의해 래퍼를 식별 할 수 있어야합니다. 미리 컨텍스트를 제거 할 수 있으려면 (적어도 부분적으로) 'ExitStack' 기능을 재 작성해야 할 수도 있습니다. –

+0

@ TadhgMcDonald-Jensen 감사합니다. Jupyter Notebook에서'ExitStack' 객체를 검사하는 것과 똑같은 것을 발견했습니다. 그들은 closure의 deque를 가지고 있는데, 이는 '__self__' 속성이 컨텍스트 관리자입니다. 알려진 해결책으로 일부 코드를 추가하겠습니다 만, 해킹 (hack) 솔루션을 줄이기를 희망했습니다. 이전에 Python Ideas에 제출하거나 직접 추가하기 전에 더 깨끗한 솔루션이 있는지 알고 싶었습니다. – arachnivore

답변

1

contextlib.ExitStack은 한 번에 모든 컨텍스트 관리자를 종료 지원 나는 이것보다 덜 '더러운'해결책이 될 수있을 기대했다. 컨텍스트 관리자는 개별적으로 팝 할 수 없습니다. 이 작업을 수행하려면 컨텍스트 관리자를 ExitStack이 아닌 다른 항목으로 추적해야합니다.

2

당신은 당신의 자신의 pop -method와 ExitStack을 확장 할 수 있습니다

from contextlib import ExitStack 
from collections import deque 

class ExitStackWithPop(ExitStack): 
    def pop(self, cm): 
     callbacks = self._exit_callbacks 
     self._exit_callbacks = deque() 
     found = None 
     while callbacks: 
      cb = callbacks.popleft() 
      if cb.__self__ == cm: 
       found = cb 
      else: 
       self._exit_callbacks.append(cb) 
     if not found: 
      raise KeyError("context manager not found") 
     found(None, None, None) 
+1

그것은'_ExitStack__self__'가 아니며 단지'__self__'입니다. 두 개의 밑줄이있는 속성은 private가 아닙니다 (모든 마법 메서드 이름을 생각해보십시오). 또한'deque'를 재 작성할 필요가 없습니다. 아이템들과'.remew'는'.__ self__ == cm'을 가지고 있습니다. –

+0

고마워요! 그것은 지금 제가 사용하고있는 솔루션에 매우 가깝습니다. 그러나 저는 서브 클래 싱에 대한 아이디어를 좋아합니다. 그렇게 깨끗해 보입니다. – arachnivore

+0

Bleh. 여기서 구현 세부 사항에 도달하고 있습니다. – user2357112