반복자가 for문을 제어하기 위해 존재하는 것처럼 콘텍스트 관리자 객체는 with문을 제어하기 위해 존재한다.
with문은 try//finally 패턴(이 패턴은 예외,return, sys.exit()호출등의 이유로 어떤 블록의 실행이 중단되더라도 이후의 일정한 코드를 반드시 실행할 수 있게 보장)을 단순화하기 위해 설계되었다.
일반적으로 finally 절 안에 있는 코드는 중요한 리소스를 해체하거나 임시로 변경된 상태를 복원하기 위해 사용된다.
콘텍스트 관리자 프로토콜은 enter()와 exit() 메서드로 구성되어 있고, with문이 시작될 때 콘텍스트 관리자 객체의 enter()메서드가 호출되므로 with 블록의 끝에서 finally절의 역할을 수행한다.
#콘텍스트 관리자로서 파일 객체의 사용 예
with open('mirror.py') as fp:
src = fp.read(60)
len(src)
fp
fp.closed.fp.encdoing
fp.read(60)
제어 흐름이 with문을 빠져나온 후에는 enter() 메서드는 반환한 객체가 아니라 켄텍스트 관리자 객체의 exit()메서드가 호출된다.
with 문의 as절은 선택적으로 open()의 경우에는 파일에 대한 참조가 필요하지만, 사용자에게 반환할 적절한 객체가 없어 None을 반환하는 콘텍스트 관리자도 있다.
from mirror import LookingGlass
with LookingGlass() as what:
print("Alice, Kitty and Snowdrop')
print(what)
class LookingGlass:
def __enter__(self):
import sys
self.original_write = sys.stdout.write
sys.stdout.write = self.reverse_write
return 'JABBERWOCKY'
def reverse_write(self, text):
self.original_write(text[::-1]])
def __exit__(self, exc_type, exc_value, traceback):
import sys
sys.stdout.write = self.original_write
if exc_type is ZeroDivisionError:
print('Please DO NOT divide by zero!')
return True