파이썬 with 문법 완벽 정리 – 자동으로 리소스를 관리하는 방법
파이썬 코드를 보다 보면 with라는 키워드를 종종 보게 된다. 특히 파일을 열거나 데이터베이스를 연결할 때 자주 등장하는데, 이게 뭔지 잘 모르면 그냥 신기한 문법처럼만 보일 수 있다.
사실 with는 파이썬에서 리소스를 안전하게 다루기 위한 도구다.
파일을 열고 닫을 때 open()과 close()를 쓰는 게 일반적인데, with를 쓰면 이런 과정을 자동으로 처리해준다. 그래서 코드가 깔끔해지고, 실수도 줄어든다.
조금 더 정확히 말하면, with는 컨텍스트 매니저(Context Manager)라는 개념을 기반으로 동작한다.
어떤 작업이 시작되고 끝날 때 자동으로 특정 동작을 해주는 방식인데, 주로 파일, DB, 네트워크, 락(lock) 같은 자원 관리에 쓰인다.
기본 문법
with open('파일경로', 'r') as 파일객체:
코드블록
예를 들어 위 코드는 파일을 열고 읽거나 쓰는 작업을 한 뒤, 자동으로 `close()`까지 해준다. 중간에 오류가 나더라도 자동으로 닫힌다. 이게 진짜 편하다.
1. 텍스트 파일 읽기
with open('example.txt', 'r', encoding='utf-8') as f:
data = f.read()
print(data)
`with` 덕분에 `f.close()`를 따로 안 써도 된다. 파이썬이 자동으로 닫아주니까.
2. 파일에 내용 쓰기
with open('output.txt', 'w') as f:
f.write("Hello, world!")
파일을 열고 문자열을 쓰고, 자동으로 닫는다. 정말 직관적이다.
3. 여러 파일 동시에 사용
with open('in.txt') as fin, open('out.txt', 'w') as fout:
fout.write(fin.read())
파일 두 개를 동시에 열고 작업할 수 있다. 이때도 각각 알아서 닫힌다.
4. 직접 만든 클래스에 with 적용
class MyContext:
def __enter__(self):
print("시작")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("끝")
with MyContext():
print("작업 중")
이처럼 `__enter__()`와 `__exit__()`를 구현하면 내가 만든 클래스도 `with` 문에 쓸 수 있다.
요약
파이썬의 `with` 문은 파일, 네트워크, DB 등 리소스를 다룰 때 실수를 줄이고 코드를 깔끔하게 해준다. 자동 정리가 핵심이다. 초보자일수록 꼭 익혀야 하는 문법 중 하나다.
예제 1. 텍스트 파일 읽기
with open('example.txt', 'r', encoding='utf-8') as f:
content = f.read()
print(content)
텍스트 파일을 열고 내용을 읽은 뒤 자동으로 닫는다. 가장 기본적인 사용 예다.
예제 2. 파일에 텍스트 쓰기
with open('log.txt', 'w') as f:
f.write("로그 기록 시작")
파일을 쓰기 모드로 열고 문자열을 기록한다. 작업이 끝나면 자동으로 저장 및 닫힘.
예제 3. 여러 파일 동시 사용
with open('source.txt', 'r') as src, open('copy.txt', 'w') as dest:
dest.write(src.read())
두 파일을 동시에 열고, 한 파일에서 읽은 내용을 다른 파일에 복사한다.
예제 4. 예외 처리와 함께 사용
try:
with open('config.json') as f:
config = f.read()
except FileNotFoundError:
print("설정 파일이 없습니다.")
파일이 없을 경우 오류를 잡아내고, 프로그램이 멈추지 않도록 한다.
예제 5. 사용자 정의 context manager
class Timer:
def __enter__(self):
import time
self.start = time.time()
return self
def __exit__(self, *args):
import time
print(f"총 소요 시간: {time.time() - self.start:.2f}초")
with Timer():
sum = 0
for i in range(1000000):
sum += i
작업 시간 측정을 위해 직접 context manager 클래스를 만들어서 사용한 예시다.