Python 컨텍스트 매니저(Context Manager)는 with 문과 함께 리소스의 획득과 해제를 자동으로 관리한다. 파일, 잠금, 데이터베이스 연결 등의 정리 코드를 보장한다.
with 문 동작 원리
python
with open('file.txt') as f:
data = f.read()
# 블록 종료 시 자동으로 f.close() 호출
# 위 코드는 아래와 동일
f = open('file.txt')
try:
data = f.read()
finally:
f.close()
enter / exit 프로토콜
python
class Timer:
import time
def __enter__(self):
self.start = __import__('time').time()
return self # as 절에 바인딩되는 값
def __exit__(self, exc_type, exc_val, exc_tb):
elapsed = __import__('time').time() - self.start
print(f'경과 시간: {elapsed:.3f}초')
return False # True 반환 시 예외 억제
with Timer() as t:
import time; time.sleep(0.1)
# 경과 시간: 0.100초
contextlib.contextmanager 데코레이터
python
from contextlib import contextmanager
@contextmanager
def managed_connection(host, port):
conn = connect(host, port) # __enter__ 역할
try:
yield conn # with 블록에 conn 제공
finally:
conn.close() # __exit__ 역할
with managed_connection('localhost', 5432) as conn:
conn.execute('SELECT 1')
contextlib 유틸리티
python
from contextlib import suppress, nullcontext, ExitStack
# suppress: 지정 예외 무시
with suppress(FileNotFoundError):
os.remove('temp.txt')
# ExitStack: 동적으로 컨텍스트 매니저 스택
with ExitStack() as stack:
files = [stack.enter_context(open(f)) for f in filenames]
# 모든 파일이 자동으로 닫힘
# nullcontext: 조건부 컨텍스트
lock = threading.Lock() if threaded else nullcontext()
with lock:
shared_resource.update()
비동기 컨텍스트 매니저
python
class AsyncDB:
async def __aenter__(self):
self.conn = await asyncpg.connect(...)
return self.conn
async def __aexit__(self, *args):
await self.conn.close()
async def main():
async with AsyncDB() as conn:
rows = await conn.fetch('SELECT * FROM users')
관련 개념