with는 파일 문법이 아니라, 작업이 끝나면 정리해야 하는 자원을 안전하게 다루는 문법입니다.
파일, 락, 연결, 세션처럼 "들어갈 때 준비하고 나올 때 정리하는" 자원이라면 try/finally보다 먼저 with를 떠올리는 편이 좋습니다.
핵심 정리
from pathlib import Path
with Path("notes.txt").open("r", encoding="utf-8") as file:
content = file.read()문법
기본형은 with resource as name:과 context manager 프로토콜을 함께 보면 됩니다.
with open("data.txt", "r", encoding="utf-8") as file:
data = file.read()자원 정리
파일처럼 끝나면 닫아야 하는 자원이면 with
파일, 락, 네트워크 연결처럼 사용 후 정리가 필요한 자원은 중간에 예외가 나도 마무리돼야 합니다.
with는 그 정리 책임을 문법 수준에서 보장해 줍니다.
with open("data.txt", "r", encoding="utf-8") as file:
data = file.read()블록을 벗어나면 성공/실패와 관계없이 닫기 로직이 호출되므로, try/finally를 직접 쓰는 부담이 줄어듭니다.
context manager 모델
내부적으로는 __enter__ / __exit__ 프로토콜
context manager는 블록 시작 시 __enter__(), 종료 시 __exit__()를 호출하는 객체입니다.
그래서 파일뿐 아니라 다양한 자원 관리 객체가 같은 with 문법을 공유할 수 있습니다.
class Demo:
def __enter__(self):
print("open")
return self
def __exit__(self, exc_type, exc, tb):
print("close")
with Demo():
print("work")이 공통 프로토콜 덕분에 with는 Python 자원 관리의 기본 문법이 됩니다.
간단한 커스텀 컨텍스트는 contextlib.contextmanager
작은 자원 관리 로직은 클래스를 만들지 않아도 contextlib.contextmanager로 만들 수 있습니다.
from contextlib import contextmanager
@contextmanager
def opened_flag(state: dict):
state["open"] = True
try:
yield state
finally:
state["open"] = False클래스가 과할 정도로 작은 자원 관리라면 이 방식이 더 가볍습니다.
예외 처리와의 경계
finally와의 경계도 같이 기억한다
예외 카드와 연결해서 보면,
- 자원 정리 패턴이 핵심이다:
with - 직접 예외 흐름을 나눠야 한다:
try/except/finally
즉 with는 "정리 보장"에 강하고, try/except는 "실패 처리"에 강합니다.
with lock:
update_shared_state()파일뿐 아니라 락, 데이터베이스 세션, 임시 설정 같은 "들어갈 때 준비하고 나올 때 정리하는" 자원 전반에 같은 문법을 쓸 수 있습니다.
블록 밖에서 자원을 다시 쓰지 않는다
with 블록이 끝나면 자원도 정리된 상태라고 보는 편이 안전합니다.
필요한 값은 블록 안에서 읽어 두고 나와야 합니다.
주의할 점
with 블록 밖에서 파일 객체를 계속 쓰면 닫힌 자원을 건드리게 됩니다. 필요한 데이터는 블록 안에서 읽어 두는 편이 안전합니다.
# ❌ 블록이 끝난 뒤 파일 객체를 사용
with open("data.txt", "r", encoding="utf-8") as file:
pass
text = file.read()
# ✅ 필요한 값을 블록 안에서 읽어 둔다
with open("data.txt", "r", encoding="utf-8") as file:
text = file.read()
# ❌ try/finally를 직접 쓰다 정리를 빼먹기 쉬움
file = open("data.txt", "r", encoding="utf-8")
data = file.read()
# ✅ 정리 보장은 with가 더 직접적
with open("data.txt", "r", encoding="utf-8") as file:
data = file.read()참고 링크
2 sources