@contextmanager 데커레이터는 콘텍스트 관리자를 생성할 때 작성하는 틀에 박힌 코드를 줄여주고, enter()와 exit() 메서드를 가진 클래스 전체를 작성하는 대신 enter() 메서드가 반환할 것을 생성하는 yield문 하나를 가진 제너레이터만 구현하면 된다.
@contextmanager로 데커레이터된 제너레이터에서 yield는 함수 본체를 두 부분으로 나누기 위해 사용되고, yield 문 앞에 있는 모든 코드는 with블록 앞에서 인터프리터가 enter()를 호출할 때, 실행되고, yield문 뒤에 있는 코드는 블록의 마지막에서 exit()가 호출될 때 실행된다.
#제너레이터로 구현한 콘텍스트 관리자
import contextlib
@contextlib.contextmanager
def looking_glass():
import sys
original_write = sys.stdout.write
sys.stdout.write = reverse_write
yield 'JABBERWORCKY'
sys.stdout.write = original_write
#looking_glass() 콘텍스트 함수 사용 예
from mirror_gen import looking_glass
with looking_glass() as what:
print('Alice, Kitty and Snowdrop')
print(what)
#예외처리를 구현한 제너레이터 기반 콘첵스트 관리자
import contextlib
@contextlib.contextmanager
def looking_glass():
import sys
original_write = sys.stdout.write
def reverse_write(text):
original_write(text[::-1])
sys.stdout.write = reverse_write
msg = ''
try:
yield "JABBERWOCKY'
except ZeroDivisionError:
msg = 'Please DO NOT divide by zero!'
finally:
sys.stodut.write = original_write
if msg:
print(msg)