AI/Python

[Python] 파일 읽고 쓰기 with문 - ContextManager

i-moo 2025. 10. 12. 14:57
반응형

Python에서 자원을 읽고 쓸 때, try-except 문을 사용하지 않고 with문을 사용한다고 한다.

try-except 문을 사용해서 파일을 읽고 쓰게 되면, finally에서 연결 끊는 코드를 안해주면 자원을 계속 실행하고 있게된다. 직접 해제해줘야함.

f = open('file.txt', 'r')
try:
    data = f.read()
    print(data)
finally:
    f.close() # 리소스를 직접 해제해야 함

with문을 사용하면 block을 벗어나면 f.close를 안해줘도 자동으로 연결을 해제해준다.

with open('file.txt', 'r') as f:
    data = f.read()
    print(data)
# with 블록을 벗어나는 순간, f.close()가 자동으로 호출됨

📌 이렇게 가능한 이유가 뭘까?

일단, with문은 __enter__와 __exit__라는 특별한 메서드를 호출하도록 설계된 문법이다.
해당 내용은 Python 공식 문서에서 확인이 가능하다.

 

PEP 343 – The “with” Statement | peps.python.org

This PEP adds a new statement “with” to the Python language to make it possible to factor out standard uses of try/finally statements.

peps.python.org

 

python with문
이 PEP에서 컨텍스트 관리자는 with 문 본문에 진입하고 종료할 때 호출되는 __enter__() 및 __exit__() 메서드를 제공합니다.

📌 Context Manager란?

Context Manager는 __enter__()와 __exit__()를 제공한다. 그리고 open()는 ContextManager 프로토콜을 따르는 객체를 반환해준다.

python open method

open() 반환하는 객체 TextIOWrapper -> TextIOWrapper는 TextIOBase를 상속받고 있고 해당 객체는 _io._IOBase를 상속받고 있다.
타고타고 들어가서 _io._IOBase 객체를 가보면 __enter__와 __exit__가 존재한다.
_io._IOBase라는 추상 클래스가 컨텍스트 매니저 프로토콜을 구현하고 있는 형태.

 

 

io.IOBase — Python Standard Library

 

tedboy.github.io

class TestContextManager:
    def __init__(self):
        print("__init__")
    
    def __enter__(self):
        print("__enter__")
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("__exit__")

t = TestContextManager()

print("="*10)

with TestContextManager() as t:
    print("__with__ start")
        
print("="*10)

# __init__
# ==========
# __init__
# __enter__
# __with__ start
# __exit__
# ==========

TestContextManager 객체를 단독으로 선언해줬을때는 __init__만 호출되고,
with문과 같이 선언해줬을때는 __init__ 메소드와 함께 __enter__, __exit__ 도 호출된다.

오히려, __enter__, __exit__ 구현안되어있는 객체를 with문과 객체를 생성할 때는 AttributeError: __enter__ 오류가 뜨게된다.

with문은 ContextManager 프로토콜을 따르는 객체와 함께 쓸 수 있음.

자원을 읽고 쓸 때, with문을 사용하지만 예외처리는 잡을 수 없기때문에 try block안에 with문 포함된 형태로 자원을 불러오는 경우가 많다고함.

Python 프로토콜과 추상클래스에대해서도 공부해야겠다.

 

contextlib — Utilities for with-statement contexts

Source code: Lib/contextlib.py This module provides utilities for common tasks involving the with statement. For more information see also Context Manager Types and With Statement Context Managers....

docs.python.org

 

📌 contextlib.contextmanager 데코레이터

ContextManager를 보다보면 contextlib 모듈이 나오는데 이건 ContextManager를 쓰기 쉽게 제공해주는 모듈이다.
클래스 형태가 아닌 함수 형태로도 훨씬 짧게 구현 가능.

from contextlib import contextmanager

@contextmanager
def  file_manager(file_name, method):
    f = open(file_name, method) # 자원 획득
    yield f		# with문으로 자원 넘김
    f.close()		# 자원 해제

with file_manager("text.txt",  "w")  as f:
    f.write("context manager")	# 넘겨받은 자원을 사용

contextmanager 데코레이터에는 무조건 yield 키워드는 무조건 들어가야한다.

yield 키워드를 기준으로 위에는 __enter__, 아래는 __exit__로 분리되기 때문이고
yield 키워드가 사용하는 함수의 경우, Generator (제너레이터) 함수라고 한다.

 

 

5-2. context manager-2

### context manager 예제 context manager를 이용해서 timer를 만드는 예제를 작성해보자. ``` import time class Timer(o…

wikidocs.net

yield가 뭐길래...? 이건 다음에 Generator(제너레이터)와 따로 정리해보겠다.👋

 

[Python] Yield 키워드와 Generator 함수

ContextManager를 공부하다가 나온 yield 키워드. [Python] 파일 읽고 쓰기 with문 - ContextManagerPython에서 자원을 읽고 쓸 때, try-except 문을 사용하지 않고 with문을 사용한다고 한다.try-except 문을 사용해서

itstudentstudy.tistory.com

 

반응형