본문 바로가기
자기 개발/Python

파이썬(Python) 공부 8편 — 파일 입출력 완전 정복 | open()·with문·read·write·CSV·JSON·pathlib까지

by conrad 2026. 3. 31.
08 / 15 Python 공부 시리즈 — 파일 입출력
← 7편: 리스트·튜플·딕셔너리·집합 보러 가기
Python 공부 시리즈 · 8편 | 파일 읽기·쓰기 · CSV · JSON · pathlib

파이썬(Python) 공부 8편
파일 입출력 완전 정복

실무에서 파이썬을 쓰다 보면 파일을 읽고 쓰는 작업이 반드시 필요합니다. 텍스트 파일 처리부터 업무 자동화에 필수인 CSV, API 통신에 쓰이는 JSON까지 파이썬 파일 입출력의 모든 것을 정리합니다.

open() 함수와 모드 with문 (컨텍스트 매니저) read / write / append CSV 파일 처리 JSON 파일 처리 pathlib

📁 open() — 파일 열기의 모든 것

파이썬에서 파일을 다루려면 먼저 open() 함수로 파일을 열어야 합니다. open(파일경로, 모드, encoding='utf-8') 형태로 사용하며, 사용 후 반드시 close()로 닫아야 합니다. (with문을 쓰면 자동으로 처리됩니다)

모드의미파일 없을 때기존 내용읽기쓰기
r읽기 (기본값)FileNotFoundError유지OX
w쓰기 (덮어씀)새로 생성삭제XO
a추가 (append)새로 생성유지·추가XO
x배타적 생성새로 생성XO (이미 있으면 오류)
r+읽기+쓰기FileNotFoundError유지OO
rb / wb바이너리 읽기/쓰기이미지·PDF 등 바이너리 파일
파이썬 파일 입출력 프로그래밍 ▲ 파이썬의 파일 입출력은 텍스트 파일부터 CSV, JSON까지 다양한 형식을 처리할 수 있다. with문을 사용하면 파일을 안전하게 열고 닫을 수 있다. (출처: Unsplash / 참고 이미지)

with문 — 파일을 안전하게 처리하는 방법

파이썬 권장 방식 with문을 쓰면 예외가 발생해도 파일이 자동으로 닫힌다

컨텍스트 매니저(Context Manager)라고 불리는 with문은 블록이 끝나면 자동으로 close()를 호출합니다. 수동으로 close()를 호출하는 방법보다 안전하고 코드가 간결합니다.

# ❌ 수동 방식 — 예외 발생 시 close()가 실행 안 될 수 있음
f = open("data.txt", "r", encoding="utf-8")
content = f.read()
f.close()   # 직접 닫아야 함

# ✅ with문 — 블록 종료 시 자동 close() 호출
with open("data.txt", "r", encoding="utf-8") as f:
    content = f.read()
# with 블록을 벗어나면 f.close() 자동 실행

# 파일 두 개 동시에 열기
with open("input.txt", "r", encoding="utf-8") as fin, \
     open("output.txt", "w", encoding="utf-8") as fout:
    fout.write(fin.read())
💡 파일 처리 시 항상 encoding='utf-8'을 명시하는 습관을 들이세요. 운영체제마다 기본 인코딩이 달라 한글이 깨지는 문제가 생길 수 있습니다.

📖 파일 읽기 — read / readline / readlines

file_read.py — 예제 파일 내용: sample.txt
# sample.txt 내용:
# 첫 번째 줄
# 두 번째 줄
# 세 번째 줄

# ① read() — 파일 전체를 하나의 문자열로
with open("sample.txt", "r", encoding="utf-8") as f:
    content = f.read()
    print(content)      # 파일 전체 출력

# ② readline() — 한 줄씩 읽기
with open("sample.txt", "r", encoding="utf-8") as f:
    line1 = f.readline()   # "첫 번째 줄\n"
    line2 = f.readline()   # "두 번째 줄\n"
    print(line1.strip())    # 줄바꿈 제거 → "첫 번째 줄"

# ③ readlines() — 모든 줄을 리스트로
with open("sample.txt", "r", encoding="utf-8") as f:
    lines = f.readlines()
    print(lines)           # ['첫 번째 줄\n', '두 번째 줄\n', '세 번째 줄']

# ④ for문으로 줄씩 순회 — 가장 메모리 효율적 (권장)
with open("sample.txt", "r", encoding="utf-8") as f:
    for line in f:
        print(line.strip())   # 한 줄씩 처리 (대용량 파일에 적합)

파일 쓰기 — write / writelines / append

file_write.py
# ① write() — 문자열 쓰기 (모드 'w' → 기존 내용 삭제 후 새로 작성)
with open("output.txt", "w", encoding="utf-8") as f:
    f.write("첫 번째 줄\n")
    f.write("두 번째 줄\n")
    print(f.write("세 번째 줄\n"))  # write()는 쓴 문자 수 반환

# ② writelines() — 리스트를 한 번에 씀 (줄바꿈 자동 없음 → 직접 포함)
lines = ["Python\n", "is\n", "fun\n"]
with open("output.txt", "w", encoding="utf-8") as f:
    f.writelines(lines)

# ③ append 모드 'a' — 기존 내용 뒤에 추가
with open("log.txt", "a", encoding="utf-8") as f:
    f.write("2026-03-31 로그 항목 추가\n")

# ④ print()로 파일에 쓰기 — file 인수 활용
with open("result.txt", "w", encoding="utf-8") as f:
    for i in range(1, 6):
        print(f"항목 {i}: {i ** 2}", file=f)  # 줄바꿈 자동 포함
⚠️ 'w' 모드는 기존 파일을 완전히 덮어씁니다
  • 기존 파일에 내용을 추가하려면 반드시 'a' 모드 사용
  • 파일 존재 여부를 먼저 확인하려면 os.path.exists() 또는 pathlib의 Path.exists() 활용

📊 CSV 파일 처리 — csv 모듈

CSV(Comma-Separated Values)는 데이터를 쉼표로 구분한 텍스트 파일 형식입니다. 엑셀·스프레드시트와 호환되며 데이터 처리에 자주 사용됩니다. 파이썬 내장 csv 모듈을 사용하면 됩니다.

csv_read_write.py
import csv

# ① CSV 쓰기 — csv.writer
data = [
    ["이름", "나이", "도시"],        # 헤더
    ["Alice", 25, "서울"],
    ["Bob",   30, "부산"],
    ["Carol", 28, "대구"],
]
with open("users.csv", "w", encoding="utf-8-sig", newline="") as f:
    writer = csv.writer(f)
    writer.writerows(data)     # 여러 행 한 번에

# ② CSV 읽기 — csv.reader
with open("users.csv", "r", encoding="utf-8-sig") as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)               # ['이름', '나이', '도시'] ...

# ③ DictReader — 헤더를 키로 사용 (더 편리)
with open("users.csv", "r", encoding="utf-8-sig") as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(f"{row['이름']}, {row['나이']}세, {row['도시']}")
# Alice, 25세, 서울 ...

# ④ DictWriter — 딕셔너리로 쓰기
users = [
    {"이름": "Dave", "나이": 22, "도시": "인천"},
]
with open("new_users.csv", "w", encoding="utf-8-sig", newline="") as f:
    fieldnames = ["이름", "나이", "도시"]
    writer = csv.DictWriter(f, fieldnames=fieldnames)
    writer.writeheader()        # 헤더 행 작성
    writer.writerows(users)
CSV 인코딩 팁 — 엑셀에서 한글 깨짐 방지
  • 엑셀에서 열 때 한글이 깨지지 않으려면 encoding='utf-8-sig' 사용 (BOM 포함 UTF-8)
  • Python 내부에서만 처리할 때는 encoding='utf-8'으로 충분
  • CSV 쓰기 시 newline='' 설정 → 줄바꿈 이중 삽입 방지

🌐 JSON 파일 처리 — json 모듈

JSON(JavaScript Object Notation)은 데이터 교환의 표준 형식으로, API 통신·설정 파일·로그 저장에 널리 쓰입니다. 파이썬 딕셔너리/리스트와 구조가 유사해 변환이 직관적입니다.

🔄
json 모듈 4가지 함수 load/dump는 파일, loads/dumps는 문자열

  • json.load(f): 파일 → 파이썬 객체 (딕셔너리/리스트)
  • json.dump(obj, f): 파이썬 객체 → 파일
  • json.loads(str): JSON 문자열 → 파이썬 객체
  • json.dumps(obj): 파이썬 객체 → JSON 문자열

💡 s가 붙으면 string(문자열), 없으면 file입니다. loads → str 입력 / dumps → str 출력
json_example.py
import json

data = {
    "name": "Alice",
    "age": 25,
    "skills": ["Python", "SQL"],
    "active": True,
}

# ① dump() — 파이썬 객체 → JSON 파일
with open("user.json", "w", encoding="utf-8") as f:
    json.dump(data, f, ensure_ascii=False, indent=2)
# ensure_ascii=False → 한글 유지 / indent=2 → 보기 좋게 들여쓰기

# ② load() — JSON 파일 → 파이썬 객체
with open("user.json", "r", encoding="utf-8") as f:
    loaded = json.load(f)
print(loaded["name"])       # Alice
print(type(loaded))         # <class 'dict'>

# ③ dumps() — 파이썬 객체 → JSON 문자열 (API 응답, 로그 출력 등)
json_str = json.dumps(data, ensure_ascii=False, indent=2)
print(json_str)
print(type(json_str))       # <class 'str'>

# ④ loads() — JSON 문자열 → 파이썬 객체 (API 응답 파싱)
api_response = '{"status": 200, "message": "OK"}'
parsed = json.loads(api_response)
print(parsed["status"])      # 200

# JSON ↔ 파이썬 타입 대응
# JSON object  → dict   / JSON array   → list
# JSON string  → str    / JSON number  → int/float
# JSON true    → True   / JSON false   → False
# JSON null    → None

📁 pathlib — 현대적인 파일 경로 처리

파이썬 3.4+에서 추가된 pathlib은 파일 경로를 객체로 다루는 현대적인 방법입니다. 문자열로 경로를 다루는 os.path보다 직관적이고 사용하기 편합니다.

pathlib_example.py
from pathlib import Path

# 경로 생성
p = Path("data/users.csv")
home = Path.home()           # 홈 디렉토리
cwd  = Path.cwd()            # 현재 작업 디렉토리

# / 연산자로 경로 조합 (OS 무관 동작)
log_path = Path("logs") / "2026" / "app.log"
print(log_path)             # logs/2026/app.log

# 경로 정보 조회
print(p.name)               # users.csv (파일명)
print(p.stem)               # users (확장자 제외)
print(p.suffix)             # .csv (확장자)
print(p.parent)             # data (상위 디렉토리)

# 존재 여부 · 종류 확인
print(p.exists())            # True / False
print(p.is_file())           # 파일인가
print(p.is_dir())            # 디렉토리인가

# 디렉토리 생성
Path("output/reports").mkdir(parents=True, exist_ok=True)
# parents=True → 중간 폴더도 생성 / exist_ok=True → 이미 있어도 오류 없음

# 파일 목록 조회
for f in Path(".").glob("*.txt"):   # 현재 폴더의 .txt 파일
    print(f.name)

for f in Path(".").rglob("*.py"):    # 하위 폴더까지 재귀적으로
    print(f)

# pathlib로 파일 읽기/쓰기 (open() 없이도 가능)
text = Path("data.txt").read_text(encoding="utf-8")
Path("output.txt").write_text("Hello!", encoding="utf-8")

📝 8편 실습 문제

실습 1 — 성적 CSV 파일 처리
  • 학생 이름·국어·영어·수학 점수가 담긴 CSV 파일 생성하기
  • 생성한 CSV를 읽어 총점·평균을 계산하고 결과를 새 CSV로 저장하기
실습 2 — JSON 설정 파일 읽고 쓰기
  • 앱 설정(이름·버전·디버그 여부·허용IP목록)을 담은 config.json 생성
  • 파일을 읽어 디버그 모드를 토글(True↔False)하고 다시 저장
practice_08.py — 예시 답안
import csv, json

# 실습 1 — 성적 CSV 처리
scores = [
    ["이름", "국어", "영어", "수학"],
    ["Alice", 90, 85, 92],
    ["Bob",   78, 88, 70],
    ["Carol", 95, 91, 89],
]
with open("scores.csv", "w", encoding="utf-8-sig", newline="") as f:
    csv.writer(f).writerows(scores)

# 읽어서 총점·평균 계산 후 저장
results = []
with open("scores.csv", "r", encoding="utf-8-sig") as f:
    for i, row in enumerate(csv.reader(f)):
        if i == 0:
            results.append(row + ["총점", "평균"])
        else:
            s = [int(x) for x in row[1:]]
            results.append(row + [sum(s), f"{sum(s)/len(s):.1f}"])
with open("scores_result.csv", "w", encoding="utf-8-sig", newline="") as f:
    csv.writer(f).writerows(results)

# 실습 2 — JSON 설정 파일 토글
config = {"app": "MyApp", "version": "1.0", "debug": False, "allowed_ips": ["127.0.0.1"]}
with open("config.json", "w", encoding="utf-8") as f:
    json.dump(config, f, ensure_ascii=False, indent=2)

with open("config.json", "r", encoding="utf-8") as f:
    cfg = json.load(f)
cfg["debug"] = not cfg["debug"]  # 토글
with open("config.json", "w", encoding="utf-8") as f:
    json.dump(cfg, f, ensure_ascii=False, indent=2)
print(f"debug 모드: {cfg['debug']}")   # debug 모드: True
8편 핵심 요약
  • open() 모드: r(읽기) w(쓰기·덮어씀) a(추가) x(새 파일만) b(바이너리)
  • with문: 블록 종료 시 자동 close() / 파일 처리 표준 패턴 / encoding='utf-8' 항상 명시
  • 읽기: read()(전체) / readline()(한 줄) / readlines()(리스트) / for line in f(대용량 권장)
  • 쓰기: write(str) / writelines(list) / print(..., file=f)
  • CSV: csv.reader/writer / DictReader/DictWriter / 엑셀 한글은 utf-8-sig
  • JSON: load/dump(파일) / loads/dumps(문자열) / ensure_ascii=False(한글 유지) / indent=2(들여쓰기)
  • pathlib: Path()로 경로 객체 생성 / /로 경로 조합 / exists() glob() mkdir() 등 편리한 메서드
다음 편 예고 9편 — 예외 처리 try/except 완전 정복

try/except/else/finally / 예외 종류 / raise / 사용자 정의 예외

🐍

※ 본 포스팅은 Python 3 공식 문서(docs.python.org)의 파일 입출력·csv·json·pathlib 레퍼런스를 기반으로 작성된 학습용 콘텐츠입니다. 코드 예시는 Python 3.10 이상 환경에서 테스트되었습니다.