파이썬 파일 읽기·쓰기
디스크에 저장하고 불러오는 법. 자동화 스크립트의 양 다리.
지금까지 우리 코드의 모든 결과는 창을 닫으면 사라졌습니다. 변수에 담은 학생 30명 데이터, 분석 결과, 사용자 로그 — 다 메모리에만. 디스크에 저장하지 않으면 그 다음에 쓸 수 없죠. 13편이 그래서 파이썬을 "스크립트" 에서 "실제 도구" 로 한 단계 올리는 챕터입니다. 입문이 끝나고 기초 묶음의 시작.
13편을 마치면 ① open 의 모드 6가지 ② with 컨텍스트 매니저 ③ 한 줄씩 vs 통째로 읽기 ④ CSV·JSON 같이 자주 만나는 형식 ⑤ pathlib 의 현대식 사용법 — 5가지가 손에 익습니다.
open 의 6가지 모드
open(파일경로, 모드) 가 기본 형태. 두 번째 인자가 무엇을 할지 정합니다.
| 모드 | 의미 | 파일 없으면 | 기존 내용 |
|---|---|---|---|
"r" | 읽기 (기본값) | FileNotFoundError | 유지 |
"w" | 쓰기 | 생성 | 덮어씀! |
"a" | 추가 | 생성 | 끝에 이어붙임 |
"x" | 생성 전용 | 생성 | 있으면 FileExistsError |
"rb" | 바이너리 읽기 | FileNotFoundError | 유지 (이미지·zip 등) |
"r+" | 읽기+쓰기 | FileNotFoundError | 유지·수정 |
open("important.txt", "w") 는 기존 내용을 즉시 0바이트로 날립니다. 추가하려면 반드시 "a". 실수로 "w" 로 열고 그냥 닫기만 해도 파일이 비게 돼요. 입문자 가장 흔한 사고 1번.
with 문 — 자동 close 의 마법
파일을 열었으면 닫아야 합니다. 안 닫으면 다른 프로그램이 못 쓰거나, 변경이 디스크에 안 반영되거나, 운영체제 핸들이 새요. with 가 이걸 자동으로.
# 옛날 방식 (실수 가능)
f = open("data.txt")
text = f.read()
f.close() # 빠뜨리거나 에러 나면 안 닫힘
# 현대 방식 (권장)
with open("data.txt") as f:
text = f.read()
# 들여쓰기 끝나면 자동 close — 예외가 나도 보장
with 는 컨텍스트 매니저라는 고급 개념의 표면입니다. 들여쓰기 블록을 빠져나가는 순간 — 정상이든 예외든 — 약속한 정리 작업이 실행돼요. 12편 try-finally 의 절제된 버전.
읽기 — 통째로·한 줄씩·반복
# 1) 통째로 한 문자열로
with open("poem.txt", encoding="utf-8") as f:
text = f.read() # 전체 — 작은 파일에만
# 2) 줄 단위 리스트
with open("poem.txt", encoding="utf-8") as f:
lines = f.readlines() # ['첫 줄\n', '둘째 줄\n', ...]
# 3) 한 줄씩 순회 — 큰 파일에도 안전 (메모리 한 줄만)
with open("huge.log", encoding="utf-8") as f:
for line in f:
if "ERROR" in line:
print(line.rstrip())
3번이 실무 정공법. 100GB 로그도 메모리 부담 없이 한 줄씩 흐릅니다. rstrip() 은 줄 끝의 \n 제거.
📌 encoding="utf-8" 은 거의 항상 명시
윈도우의 기본 인코딩(cp949)·맥/리눅스(utf-8) 가 달라 한글 파일이 OS 사이를 오갈 때 깨집니다. encoding="utf-8" 한 줄로 모든 환경에서 같은 동작. 2026년 기준 utf-8 이 표준입니다.
쓰기 — write·writelines·print 리다이렉트
# 한 문자열 쓰기 (덮어쓰기)
with open("hello.txt", "w", encoding="utf-8") as f:
f.write("안녕\n파이썬\n")
# 여러 줄 한꺼번에
lines = ["줄 1\n", "줄 2\n", "줄 3\n"]
with open("multi.txt", "w", encoding="utf-8") as f:
f.writelines(lines) # \n 안 붙여줌, 본인이 포함
# print 로 파일에 쓰기 (덜 일반적이지만 깔끔)
with open("log.txt", "a", encoding="utf-8") as f:
print(f"[2026-05-13] 작업 완료", file=f)
write 는 줄바꿈을 자동으로 안 붙입니다. 매 줄 끝에 \n 필요. print(..., file=f) 패턴은 print 의 줄바꿈을 그대로 활용 — 로그 파일 작성에서 자주 쓰여요.
CSV·JSON — 자주 만나는 두 형식
CSV — 콤마로 구분된 표
import csv
# 쓰기
with open("scores.csv", "w", encoding="utf-8", newline="") as f:
w = csv.writer(f)
w.writerow(["이름", "점수"])
w.writerow(["준성", 88])
w.writerow(["수민", 92])
# 읽기 — 첫 줄을 키로 (DictReader 권장)
with open("scores.csv", encoding="utf-8") as f:
for row in csv.DictReader(f):
print(f"{row['이름']}: {row['점수']}")
# 준성: 88
# 수민: 92
newline="" 는 csv 모듈의 약속 — 빼면 윈도우에서 줄 사이에 빈 줄이 생깁니다.
JSON — 설정·API 단골
import json
# 저장
data = {"users": [{"name": "준성", "age": 30}], "version": 2}
with open("config.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
# 읽기
with open("config.json", encoding="utf-8") as f:
cfg = json.load(f)
print(cfg["users"][0]["name"]) # 준성
한글이 들어가면 ensure_ascii=False 를 잊지 마세요. 안 그러면 "준성" 같은 유니코드 이스케이프로 저장됩니다.
pathlib — 경로의 현대식 다루기
from pathlib import Path
p = Path("data") / "scores.csv" # OS 무관한 경로 합성
p.parent.mkdir(parents=True, exist_ok=True) # 폴더 없으면 생성
p.write_text("이름,점수\n준성,88\n", encoding="utf-8")
text = p.read_text(encoding="utf-8")
# 디렉토리 순회
for f in Path("logs").glob("*.log"):
print(f.name, f.stat().st_size)
os.path 보다 짧고 OS 차이를 자동 처리. 2026년 신규 코드는 거의 pathlib 입니다.
다음 미션 — REPL 에서: ① diary.txt 에 오늘 날짜와 한 줄을 추가(append) ② CSV 에 본인 한 주 매출 7일치 저장 후 평균 계산해 출력 ③ JSON 파일을 읽고 한 키만 바꿔 다시 저장.
다음 편 미리보기
14편 — "파이썬 클래스 입문": class·__init__·메서드·속성. 객체지향의 첫 발걸음.
← 12편 "예외 처리" · 다음: 14편 "클래스 입문"