2014-11-11 11 views
4

, 우리는 들여 쓰기/중첩 한 레벨 만 사용하여 많은 컨텍스트 핸들러를 입력 할 수 있습니다컨텍스트 관리자를 사용하는 방법은 무엇입니까? 문으로 사용

>>> from contextlib import contextmanager 
>>> @contextmanager 
... def frobnicate(n): 
...  print('frobbing {}'.format(n)) 
...  yield 
... 
>>> frob1 = frobnicate(1) 
>>> frob2 = frobnicate(2) 
>>> with frob1, frob2: 
...  pass 
... 
frobbing 1 
frobbing 2 

을하지만이 작동하지 않습니다

>>> frobs = [frobnicate(1), frobnicate(2)] 
>>> with *frobs: 
...  pass 
# SyntaxError: invalid syntax 

우리가 어떻게 를 입력 할 수 있습니다 n 컨텍스트 관리자가 수동으로 각 항목을 작성하지 않아도됩니까?

답변

6

python2.7이 정확히 수행 할 수있는 것은 contextlib.nested 이었지만 오류가 발생하기 쉬운 이유로 인해 사용되지 않았습니다.

이 함수에는 두 가지 단점이있어 사용되지 않게되었습니다. 첫째, 함수가 호출되기 전에 컨텍스트 관리자가 모두 생성되므로 내부 컨텍스트 관리자의 __new__()__init__() 메서드는 실제로 외부 컨텍스트 관리자의 범위에서 다루지 않습니다. 예를 들어 두 번째 파일을 여는 데 예외가 발생하면 첫 번째 파일이 즉시 닫히지 않으므로 두 파일을 여는 데 nested()을 사용하면 프로그래밍 오류가 발생합니다. 내부 콘텍스트 관리자 중 하나의 __enter__() 방법 걸려 외측 콘텍스트 관리자 중 하나의 __exit__() 방법에 의해 억제되고, 예외가 발생하는 경우

둘째,이 구조는 오히려로 본문 스킵보다 RuntimeError에 인상 할 성명서.

from contextlib import ExitStack 

with ExitStack() as stack: 
    contexts = [stack.enter_context(frobnicate(i)) for i in range(2)] 
    ... 

이 python2.x 코드에 백 포트에 대한 contextlib2를 참조하십시오

python3.3과 같을 것이다 contextlib.ExitStack와 더 나은 일을한다.