PHpullh
학습 라이브러리/Python/컨텍스트 매니저 — with & __enter__/__exit__

PYTHON · 디자인패턴

컨텍스트 매니저 — with & __enter__/__exit__

with 문은 리소스의 획득과 해제를 자동으로 관리합니다. __enter____exit__ 매직 메서드를 구현하거나, contextlib.contextmanager 데코레이터로 간단히 만들 수 있습니다.

디자인패턴중급context-managerwithresource-managementcontextlib

핵심 설명

with 문은 리소스의 획득과 해제를 자동으로 관리합니다. __enter____exit__ 매직 메서드를 구현하거나, contextlib.contextmanager 데코레이터로 간단히 만들 수 있습니다.

Python code

from contextlib import contextmanager
import time

# 1. 클래스 기반 컨텍스트 매니저
class Timer:
    def __enter__(self):
        self.start = time.perf_counter()
        return self  # with ... as 변수에 바인딩

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.elapsed = time.perf_counter() - self.start
        print(f"경과 시간: {self.elapsed:.4f}초")
        return False  # True면 예외를 억제

# 2. 제너레이터 기반 컨텍스트 매니저
@contextmanager
def managed_resource(name):
    print(f"[{name}] 리소스 획득")
    try:
        yield name  # with ... as 변수에 전달
    except Exception as e:
        print(f"[{name}] 예외 발생: {e}")
        raise
    finally:
        print(f"[{name}] 리소스 해제")

# 3. 다중 컨텍스트 매니저
with Timer() as t:
    total = sum(range(1_000_000))
    print(f"합계: {total}")

with managed_resource("DB") as db:
    print(f"  {db} 연결로 작업 수행 중...")

# Python 3.10+ 괄호로 여러 개 관리
# with (
#     managed_resource("DB") as db,
#     managed_resource("Cache") as cache,
# ):
#     print(f"  {db}와 {cache} 동시 사용")

학습 팁

__exit__에서 True를 반환하면 발생한 예외가 억제됩니다. 예외 로깅 후 정상 흐름을 유지하고 싶을 때 유용하지만 남용하면 디버깅이 어려워집니다.

주의할 점

__exit__에서 예외 처리를 깜빡하면 리소스 누수가 발생할 수 있습니다. finally 블록처럼 정리 코드는 반드시 실행되도록 작성하세요.

자주 묻는 질문

컨텍스트 매니저 — with & __enter__/__exit__란 무엇인가요?

with 문은 리소스의 획득과 해제를 자동으로 관리합니다. __enter__ 와 __exit__ 매직 메서드를 구현하거나, contextlib.contextmanager 데코레이터로 간단히 만들 수 있습니다.

컨텍스트 매니저 — with & __enter__/__exit__ 학습 시 주의할 점은 무엇인가요?

__exit__ 에서 예외 처리를 깜빡하면 리소스 누수가 발생할 수 있습니다. finally 블록처럼 정리 코드는 반드시 실행되도록 작성하세요.