PythonPython 기초 · 5입문

파일 입출력 — 데이터를 읽고 저장하기

Python파일입출력CSVJSONwith구문

데이터를 파일로 저장해야 하는 이유

프로그램이 종료되면 변수의 값은 사라집니다. 파일로 저장해야 다음에 다시 사용할 수 있습니다.

flowchart LR
    subgraph FILE["파일 입출력"]
        W["쓰기 (Write)\n데이터 → 파일"]
        R["읽기 (Read)\n파일 → 데이터"]
    end

    MEM["메모리\n(변수)"] --> W --> DISK["디스크\n(파일)"]
    DISK --> R --> MEM

파일 쓰기

# with 구문 사용 (자동으로 파일 닫힘)
with open("hello.txt", "w", encoding="utf-8") as f:
    f.write("안녕하세요!\n")
    f.write("파이썬 파일 쓰기 예제입니다.\n")

# 여러 줄 한 번에 쓰기
lines = ["첫 번째 줄\n", "두 번째 줄\n", "세 번째 줄\n"]
with open("lines.txt", "w", encoding="utf-8") as f:
    f.writelines(lines)

파일 모드:

모드설명
"w"쓰기 (기존 내용 덮어씀)
"a"추가 (기존 내용 뒤에 붙임)
"r"읽기 (기본값)

파일 읽기

# 전체 내용 읽기
with open("hello.txt", "r", encoding="utf-8") as f:
    content = f.read()
    print(content)

# 한 줄씩 읽기
with open("hello.txt", "r", encoding="utf-8") as f:
    for line in f:
        print(line.strip())  # strip()으로 줄바꿈 제거

# 모든 줄을 리스트로
with open("hello.txt", "r", encoding="utf-8") as f:
    lines = f.readlines()   # ['첫줄\n', '둘째줄\n', ...]

파일 존재 여부 확인

import os
from pathlib import Path

# os 방식
if os.path.exists("hello.txt"):
    print("파일 있음")

# pathlib 방식 (현대적)
path = Path("hello.txt")
if path.exists():
    print(f"파일 크기: {path.stat().st_size} bytes")

# 디렉토리 생성
Path("output").mkdir(exist_ok=True)   # 이미 있어도 에러 없음
Path("a/b/c").mkdir(parents=True, exist_ok=True)  # 중간 폴더도 생성

CSV 파일 처리

import csv

# CSV 쓰기
students = [
    ["이름", "나이", "점수"],
    ["철수", 20, 85],
    ["영희", 22, 92],
    ["민준", 21, 78],
]

with open("students.csv", "w", newline="", encoding="utf-8-sig") as f:
    writer = csv.writer(f)
    writer.writerows(students)

# CSV 읽기 (딕셔너리로)
with open("students.csv", "r", encoding="utf-8-sig") as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(f"{row['이름']}: {row['점수']}점")

JSON 파일 처리

import json

# 딕셔너리를 JSON 파일로 저장
config = {
    "model": "gpt-4o-mini",
    "temperature": 0.7,
    "max_tokens": 1000,
    "system_prompt": "친절한 어시스턴트입니다."
}

with open("config.json", "w", encoding="utf-8") as f:
    json.dump(config, f, ensure_ascii=False, indent=2)

저장된 파일:

{
  "model": "gpt-4o-mini",
  "temperature": 0.7,
  "max_tokens": 1000,
  "system_prompt": "친절한 어시스턴트입니다."
}
# JSON 파일 읽기
with open("config.json", "r", encoding="utf-8") as f:
    loaded = json.load(f)

print(loaded["model"])        # gpt-4o-mini
print(loaded["temperature"])  # 0.7

실전: 대화 기록 저장/불러오기

LLM 챗봇의 대화 기록을 파일로 관리합니다.

import json
from datetime import datetime
from pathlib import Path

HISTORY_DIR = Path("chat_history")
HISTORY_DIR.mkdir(exist_ok=True)

def save_conversation(session_id: str, messages: list):
    """대화 기록을 JSON 파일로 저장합니다."""
    data = {
        "session_id": session_id,
        "saved_at": datetime.now().isoformat(),
        "messages": messages
    }
    
    filepath = HISTORY_DIR / f"{session_id}.json"
    with open(filepath, "w", encoding="utf-8") as f:
        json.dump(data, f, ensure_ascii=False, indent=2)
    
    print(f"저장됨: {filepath}")

def load_conversation(session_id: str) -> list:
    """저장된 대화 기록을 불러옵니다."""
    filepath = HISTORY_DIR / f"{session_id}.json"
    
    if not filepath.exists():
        return []   # 기록 없으면 빈 리스트
    
    with open(filepath, "r", encoding="utf-8") as f:
        data = json.load(f)
    
    return data["messages"]

# 사용 예시
messages = [
    {"role": "user", "content": "안녕!"},
    {"role": "assistant", "content": "안녕하세요!"}
]

save_conversation("user_001", messages)
loaded = load_conversation("user_001")
print(loaded[0]["content"])   # 안녕!

실전: 로그 파일 쌓기

from datetime import datetime

def write_log(message: str, level: str = "INFO"):
    """로그를 파일에 추가합니다."""
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    log_entry = f"[{timestamp}] [{level}] {message}\n"
    
    with open("app.log", "a", encoding="utf-8") as f:  # "a"는 추가 모드
        f.write(log_entry)
    
    print(log_entry.strip())

write_log("서버 시작")
write_log("사용자 로그인: 철수", "INFO")
write_log("파일을 찾을 수 없음", "ERROR")

pathlib: 경로 다루기

from pathlib import Path

# 경로 조합
base = Path(".")
data_dir = base / "data"
file_path = data_dir / "users.json"

print(file_path)            # data/users.json
print(file_path.name)       # users.json
print(file_path.stem)       # users
print(file_path.suffix)     # .json
print(file_path.parent)     # data

# 특정 확장자 파일 찾기
for json_file in Path(".").glob("**/*.json"):
    print(json_file)

정리

작업코드
텍스트 쓰기open("f.txt", "w") as f: f.write(...)
텍스트 읽기open("f.txt", "r") as f: f.read()
내용 추가open("f.txt", "a") as f: f.write(...)
JSON 저장json.dump(data, f, ensure_ascii=False)
JSON 읽기json.load(f)
CSV 쓰기csv.writer(f).writerows(data)
CSV 읽기csv.DictReader(f)
경로 처리Path("dir") / "file.txt"

다음 편에서는 예외 처리 — 오류가 발생해도 프로그램이 멈추지 않게 만드는 방법을 배웁니다.

궁금한 점이 있으신가요?

협업·의뢰는 아래로, 가벼운 소통은 인스타그램 @bluefox._.hi도 환영이에요.