프로그래밍Python 백엔드 개발자

파이썬에서 컨텍스트 관리자(Context Manager)는 어떻게 작동하며, 왜 필요한지, __enter__ 및 __exit__ 프로토콜을 통해 자신의 컨텍스트 관리자를 어떻게 구현할 수 있는지? 주의해야 할 사항은 무엇인가요?

Hintsage AI 어시스턴트로 면접 통과

답변.

컨텍스트 관리자with 블록에 들어가고 나오는 행동을 정의하는 객체로, 자원(파일, 연결 등)의 자동 관리를 제공합니다. 클래스 내에서 __enter____exit__ 메서드를 사용하거나 contextlib 모듈의 @contextmanager 데코레이터를 통해 구현할 수 있습니다.

구현 예시:

class FileManager: def __init__(self, filename, mode): self.filename = filename self.mode = mode self.file = None def __enter__(self): self.file = open(self.filename, self.mode) return self.file def __exit__(self, exc_type, exc_val, exc_tb): if self.file: self.file.close() with FileManager('test.txt', 'w') as f: f.write('Hello')

주의 사항: __exit__에서 예외를 제대로 처리하여 에러를 억제하기 위해 True를 반환하고, 자원을 열어두지 않도록 주의해야 합니다.

함정 질문.

질문: with 블록 내에서 예외가 발생하면, Python은 __exit__ 메서드를 호출하나요? 에러 매개변수는 어떻게 전달되나요?

답변: 네, __exit__ 메서드는 항상 호출되며, 예외가 발생해도 호출됩니다. 이 때 예외 유형, 값 및 traceback이 전달됩니다. __exit__True를 반환하면 예외가 억제됩니다.

class Simple: def __enter__(self): print('Enter') def __exit__(self, exc_type, exc_val, exc_tb): print('Exit') print(exc_type, exc_val) return True # 오류가 "밖으로" 발생하지 않음 with Simple(): raise ValueError('boom!')

주제에 대한 주의 부족으로 인한 실제 오류 예시.


이야기

파일 디스크립터 작업을 위한 사용자 정의 관리자의 __exit__를 구현하는 것을 잊어버려서 예외가 발생했을 때 파일이 닫히지 않아 파일 디스크립터 누수와 많은 파일 작업 시 오류가 발생했습니다.

이야기

데이터베이스 관리를 위해 외부 컨텍스트 관리자를 사용했는데, 이 관리자가 모든 예외에 대해 __exit__에서 True를 반환했습니다. 이로 인해 오류가 "무시"되었고, 트랜잭션이 성공했다고 판단하여 데이터 무결성이 손상되었습니다.

이야기

contextlib 모듈의 @contextmanager 데코레이터를 사용했지만, 코드가 실패할 때 yield 내부에서 예외를 처리하는 것을 잊어버려 소켓 연결이 닫히지 않아 서버가 열린 포트와 함께 "멈췄습니다."