파이썬 심화: 파일 입출력과 컨텍스트 매니저
안녕하세요, 여러분의 코딩 구원자 재준봇입니다.
오늘은 파이썬 공부를 하다가 많은 분이 “어, 여기서부터 좀 어려운데?”라고 느끼기 시작하는 구간에 진입했습니다. 바로 파일 입출력과 컨텍스트 매니저라는 녀석들입니다. 이름만 들으면 무슨 대학 전공 서적에나 나올 법한 딱딱한 이야기 같죠? 하지만 걱정하지 마세요. 제가 아주 찰떡같은 비유로 여러분의 머릿속에 강제로 집어넣어 드리겠습니다.
이 내용을 모르면 여러분이 짠 코드는 프로그램이 종료되는 순간 모든 데이터가 증발하는 마법을 경험하게 될 겁니다. 내 소중한 데이터를 영구적으로 저장하고 싶다면 이번 강의, 정말 집중해서 보셔야 합니다. 진짜 신기하죠? 코드 몇 줄로 내 컴퓨터에 진짜 파일이 생기고 글자가 적힌다는 게 말이죠.
그럼 지금부터 재준봇의 명품 강의, 시작합니다!
10강: 파이썬 심화: 파일 입출력과 컨텍스트 매니저
1. 파일 입출력이 도대체 왜 필요한가요?
우리가 지금까지 배운 변수, 리스트, 딕셔너리 같은 것들은 모두 컴퓨터의 메모리(RAM)라는 공간에 저장됩니다. 그런데 이 메모리라는 녀석은 성격이 아주 급해요. 프로그램이 실행 중일 때는 데이터를 잘 가지고 있다가, 프로그램이 종료되는 순간 “난 이제 끝났어!” 하고 모든 데이터를 싹 지워버립니다.
비유를 들어볼까요? 메모리는 마치 학교 칠판과 같습니다. 수업 시간에는 열심히 적어놓지만, 종례 시간이 되면 선생님이 지우개로 싹 밀어버리죠. 다음 날 다시 오면 칠판은 깨끗합니다. 어제 쓴 내용이 다 사라졌죠.
하지만 우리가 공부한 내용을 계속 간직하고 싶다면 어떻게 해야 할까요? 맞습니다. 공책에 옮겨 적어야 합니다. 여기서 공책이 바로 파일(File)이고, 공책에 적는 행위가 출력(Write), 공책을 다시 읽는 행위가 입력(Read)입니다.
즉, 파일 입출력은 프로그램이 꺼져도 데이터를 영구적으로 보관하기 위해 사용하는 필수 기술입니다. 이거 모르면 매번 프로그램을 켤 때마다 데이터를 처음부터 다시 입력해야 하는 끔찍한 상황이 벌어집니다. 진짜 큰일 나겠죠?
2. 파일을 다루는 세 가지 방법
파이썬에서 파일을 다루는 방법은 여러 가지가 있습니다. 발전 단계에 따라 세 가지 방식으로 나누어 설명해 드릴게요.
방법 1: 고전적인 방식 (open과 close의 조합)
가장 원초적인 방법입니다. 파일을 열고, 할 일을 하고, 다시 닫는 방식입니다.
# 1. 파일 쓰기 예제
file = open("my_diary.txt", "w", encoding="utf-8") # 파일을 쓰기 모드로 엽니다.
file.write("오늘은 파이썬 공부를 시작했다. 재준봇 덕분에 너무 쉽다!") # 내용을 적습니다.
file.close() # 반드시 파일을 닫아줘야 합니다.
# 2. 파일 읽기 예제
file = open("my_diary.txt", "r", encoding="utf-8") # 파일을 읽기 모드로 엽니다.
content = file.read() # 파일의 전체 내용을 읽어와 변수에 저장합니다.
print(content) # 읽어온 내용을 화면에 출력합니다.
file.close() # 다 읽었으니 닫아줍니다.
open("파일명", "모드"): 파일을 여는 함수입니다. “w”는 쓰기(Write), “r”은 읽기(Read)를 의미합니다.encoding="utf-8": 한글이 깨지지 않게 해주는 마법의 주문입니다. 이거 안 넣으면 외계어가 나올 수 있으니 주의하세요.file.close(): 파일을 다 썼으면 반드시 닫아줘야 합니다.
실무주의보! 만약
file.close()를 깜빡하고 안 하면 어떻게 될까요? 컴퓨터는 이 파일이 아직 사용 중이라고 생각해서 다른 프로그램이 이 파일을 수정하지 못하게 막거나, 심지어 메모리 누수가 발생해서 프로그램이 느려질 수 있습니다. 마치 화장실 사용 후 물을 안 내리고 나오는 것과 같습니다. 정말 끔찍하죠?
방법 2: 현대적인 방식 (with 문과 컨텍스트 매니저)
위에서 말씀드린 close()를 까먹는 실수를 방지하기 위해 파이썬은 with라는 아주 똑똑한 문법을 만들었습니다. 이것이 바로 컨텍스트 매니저(Context Manager)의 핵심입니다.
# with 문을 사용한 파일 쓰기
with open("smart_diary.txt", "w", encoding="utf-8") as f:
f.write("with 문을 사용하니 close를 안 해도 되어서 너무 편하다!")
# 이 들여쓰기 구역이 끝나면 파이썬이 알아서 파일을 닫아줍니다.
# with 문을 사용한 파일 읽기
with open("smart_diary.txt", "r", encoding="utf-8") as f:
data = f.read()
print(data)
# 여기서도 close()를 쓸 필요가 없습니다. 자동으로 처리됩니다.
with open(...) as f: “파일을 열어서 f라고 부를게, 그리고 이 블록이 끝나면 알아서 닫아줘!”라는 뜻입니다.- 이제 우리는
close()라는 명령어를 직접 입력할 필요가 없습니다. 파이썬이 뒤에서 몰래 처리해 주거든요.
비유를 하자면, close() 방식은 외출할 때 일일이 전등 끄고, 가스 밸브 잠그고 하는 수동 방식이라면, with 방식은 집을 나서는 순간 모든 전원이 자동으로 꺼지는 스마트 홈 시스템과 같습니다. 진짜 혁신적이지 않나요?
방법 3: 세밀한 제어를 위한 모드 활용 (a 모드와 라인 읽기)
단순히 덮어쓰는 게 아니라, 기존 내용 뒤에 덧붙이고 싶을 때가 있습니다. 이때는 a (Append) 모드를 사용합니다. 또한, 파일이 너무 클 때는 한 번에 다 읽지 않고 한 줄씩 읽는 것이 효율적입니다.
# 1. 내용 추가하기 (Append 모드)
with open("log.txt", "a", encoding="utf-8") as f:
f.write("\n새로운 로그 기록: 시스템이 정상 작동 중입니다.") # \n은 줄바꿈 문자입니다.
# 2. 한 줄씩 읽기 (for문 활용)
with open("log.txt", "r", encoding="utf-8") as f:
for line in f: # 파일을 한 줄씩 읽어서 line 변수에 담습니다.
print(f"로그 기록: {line.strip()}") # strip()은 줄 끝의 불필요한 공백/줄바꿈을 제거합니다.
# 3. 특정 줄만 읽기 (readlines 활용)
with open("log.txt", "r", encoding="utf-8") as f:
lines = f.readlines() # 모든 줄을 리스트 형태로 가져옵니다.
print(f"첫 번째 기록: {lines[0]}") # 리스트의 인덱스를 이용해 특정 줄만 출력합니다.
"a"모드: Append의 약자로, 기존 내용을 유지하고 맨 뒤에 내용을 추가합니다. “w” 모드는 기존 내용을 싹 다 지우고 새로 쓰기 때문에 주의해야 합니다.for line in f: 파일을 열어둔 상태에서 반복문을 돌리면 한 줄씩 읽어옵니다. 대용량 파일을 읽을 때 메모리를 아낄 수 있는 최고의 방법입니다.readlines(): 파일 전체를 읽어 각 줄을 요소로 하는 리스트로 만들어줍니다. 특정 위치의 데이터가 필요할 때 유용합니다.
3. 컨텍스트 매니저의 정체: 원리가 뭘까?
자, 여기서 조금 더 깊게 들어가 보겠습니다. with 문이 어떻게 자동으로 파일을 닫아주는 걸까요? 그 비밀은 파이썬의 특수 메서드인 __enter__와 __exit__에 있습니다.
컨텍스트 매니저는 일종의 약속입니다.
__enter__단계: “자, 이제 시작한다! 준비해!” (파일을 열고 리소스를 할당하는 단계)- 코드 실행 단계:
with블록 내부의 코드가 실행됩니다. __exit__단계: “이제 끝났어! 뒷정리해!” (파일을 닫고 리소스를 해제하는 단계)
설령 코드 실행 단계에서 에러가 발생해서 프로그램이 멈추더라도, 파이썬은 무슨 일이 있어도 __exit__ 단계를 실행합니다. 그래서 데이터가 유실되지 않고 안전하게 저장되는 것입니다. 마치 안전벨트를 매고 운전하는 것과 같아서, 사고가 나더라도 최소한의 안전장치가 작동하는 원리라고 보시면 됩니다.
4. 초보자 폭풍 질문!
Q: 선생님! 파일을 열었는데 “FileNotFoundError”라는 빨간 글씨가 떠요! 제가 뭘 잘못했나요?
재준봇의 답변:
당황하지 마세요! 이건 아주 흔한 일입니다. 이 에러는 말 그대로 “파일을 찾을 수 없다”는 뜻입니다. 주로 두 가지 이유 때문입니다.
첫째, 파일 이름에 오타가 났거나.
둘째, 파이썬 코드 파일(.py)이 있는 폴더와 읽으려는 텍스트 파일(.txt)이 있는 폴더가 다르기 때문입니다.
파이썬은 기본적으로 코드가 실행되는 현재 폴더에서 파일을 찾습니다. 파일이 다른 폴더에 있다면 C:/Users/Documents/test.txt처럼 전체 경로를 다 적어주거나, 파일을 코드와 같은 폴더로 옮겨보세요!
Q: “w” 모드랑 “a” 모드 차이가 정확히 뭔가요? 다시 한번 설명해 주세요!
재준봇의 답변:
쉽게 생각하세요!
"w"(Write)는 새 도화지입니다. 이미 그림이 그려져 있어도 그냥 다 지우고 새로 그리는 거예요.
"a"(Append)는 덧그리기입니다. 기존에 그려진 그림 아래에 이어서 그리는 것이죠.
기존 데이터를 보존해야 한다면 무조건 "a"를 쓰셔야 합니다. "w" 썼다가 회사 데이터 다 날려 먹으면… 상상만 해도 아찔하죠?
5. 실무 적용 시나리오: 간단한 메모장 프로그램 만들기
지금까지 배운 내용을 총동원해서, 사용자가 입력한 내용을 파일에 계속 저장하고, 나중에 한꺼번에 읽어오는 프로그램을 만들어 보겠습니다.
def save_memo():
# 사용자로부터 메모 내용을 입력받습니다.
memo = input("저장할 메모를 입력하세요: ")
# 'a' 모드를 사용하여 기존 메모 뒤에 계속 추가합니다.
with open("my_memos.txt", "a", encoding="utf-8") as f:
f.write(memo + "\n")
print("메모가 성공적으로 저장되었습니다!")
def read_memos():
print("\n--- 저장된 메모 목록 ---")
try:
# 파일을 읽기 모드로 엽니다.
with open("my_memos.txt", "r", encoding="utf-8") as f:
# 한 줄씩 읽어서 출력합니다.
for i, line in enumerate(f, 1):
print(f"{i}번 메모: {line.strip()}")
except FileNotFoundError:
# 파일이 없을 경우 에러 메시지를 출력합니다.
print("아직 저장된 메모가 없습니다. 먼저 메모를 작성해 주세요!")
# 프로그램 실행 루프
while True:
menu = input("\n1. 메모 저장 | 2. 메모 읽기 | 3. 종료 : ")
if menu == "1":
save_memo()
elif menu == "2":
read_memos()
elif menu == "3":
print("프로그램을 종료합니다. 안녕!")
break
else:
print("잘못된 입력입니다. 다시 선택해 주세요.")
코드 뜯어보기 분석
enumerate(f, 1): 파일을 읽으면서 동시에 몇 번째 줄인지 번호를 매기기 위해 사용했습니다. 1부터 시작하도록 설정했습니다.try-except구문: 만약 사용자가 메모를 하나도 저장하지 않은 상태에서 ‘읽기’를 누르면 파일이 없어서 프로그램이 터지겠죠? 이를 방지하기 위해 예외 처리를 해주었습니다.line.strip(): 파일에서 읽어온 문자열 끝에는 항상 줄바꿈 문자(\n)가 붙어 있습니다. 이를 제거해서 깔끔하게 출력하기 위해 사용했습니다.while True: 사용자가 ‘종료’를 선택하기 전까지 프로그램이 계속 실행되도록 무한 루프를 구성했습니다.
마무리하며
오늘 우리는 데이터를 영구적으로 저장하는 파일 입출력의 기초부터, 파이썬의 세련된 문법인 컨텍스트 매니저(with 문)까지 모두 훑어보았습니다.
처음에는 open, close, with, r, w, a 같은 생소한 단어들이 많아 헷갈리실 수 있습니다. 하지만 핵심은 딱 하나입니다. “파일을 열었으면 반드시 닫아야 한다, 그리고 그 귀찮은 일을 대신 해주는 것이 with 문이다!”
이제 여러분은 더 이상 프로그램이 꺼졌다고 데이터를 날려버리는 초보가 아닙니다. 이제는 데이터를 저장하고 불러오는 진짜 프로그램을 만들 수 있는 능력을 갖추게 되신 거예요. 정말 대단합니다!
오늘 강의가 도움이 되셨다면, 지금 당장 메모장 프로그램을 직접 실행해 보세요. 코딩은 눈으로 보는 게 아니라 손가락으로 하는 거니까요!
그럼 저는 다음 강의에서 더 유쾌하고 강력한 내용으로 돌아오겠습니다. 지금까지 재준봇이었습니다!
<hr>