본문 바로가기
프로그래밍/Python 관련 정보

[Pythonic Programming] Context manager

by 물박사의 저장공간 2024. 10. 26.

컨텍스트 관리자(Context Manager)는 자원 관리가 필요한 작업을 간결하고 안전하게 처리할 수 있도록 도와주는 파이썬 기능입니다. 보통 파일 입출력, 데이터베이스 연결, 스레드 락과 같은 작업을 수행할 때 사용되며, 자원을 열고 닫는 과정에서 발생할 수 있는 오류를 최소화하고 자동으로 자원을 해제해 줍니다. 쉽게 말해, 특정 작업의 시작과 끝에 정해진 행동을 수행하도록 하는 녀석이지요. 

 

context manager를 사용하지 않고 파일을 여는 코드를 생각해볼까요?

file = open('somefile', 'w')
try:
    file.write('Hola')
finally:
    file.close()

 

위와 같은 코드를 뭔가 좀더 pythonic 하게 바꿀 때 context manager를 사용하면 됩니다. 

with open('some_file', 'w') as opened_file:
    opened_file.write('Hola')

 

with 문은 __enter__ 메서드를 호출하고 이 함수가 무엇을 반환하든 as 이후에 지정된 변수에 할당합니다.

__enter__은 컨텍스트의 시작에서 수행할 작업을, __exit__는 컨텍스트가 종료될 때 수행되는 코드를 담고 있습니다. 

 

컨택스트 관리자를 클래스에서 직접 구현할 수 도 있습니다. 

class BackupHandler:
    def __enter__(self):
        print("Stop DB") # 사전 작업
        return self

    def __exit__(self, exc_type, ex_value, ex_traceback):
        print("Start DB") # 사후 작업

    def backup(self):
        print("Backup DB")


with BackupHandler() as handler:
    handler.backup() # __enter__의 return 값

 

참고) __exit__ 메서드가 True를 반환하도록 하면 예외가 발생해도 암묵적으로 넘어간다

 

 

굳이 인자를 받을 필요가 없는 경우에는 @contextlib.contextmanager 데코레이터를 활용해서  __enter__ , __exit__를 만들지 않고 사용할 수도 있습니다. 

from contextlib import contextmanager

@contextmanager
def file_open(file_name, mode):
    file = open(file_name, mode)
    yield file
    file.close()

# 사용 예시
with file_open('sample.txt', 'w') as f:
    f.write("Hello from context manager")
# with 블록이 끝나면 파일이 자동으로 닫힘