Python 강좌 / CSV 파일 읽고 쓰기

CSV는 행과 열을 텍스트로 저장하는 형식이며 csv 모듈로 따옴표와 구분자를 처리해야 합니다. DictReader가 읽은 필드도 기본적으로 문자열이므로 금액 같은 숫자는 별도로 검증하고 변환합니다.

split으로 CSV를 읽으면 안 되는 이유

필드 안의 쉼표나 줄바꿈은 따옴표로 감쌀 수 있습니다. split(",")는 이런 규칙을 해석하지 못합니다. csv 모듈은 구분자·따옴표 등 형식을 처리하고 DictReader는 첫 행의 이름으로 각 필드를 연결합니다. 열 이름이 중복되거나 필드 수가 다를 때도 입력 정책을 정해야 합니다.

관련 동작과 지원 조건은 CSV 파일 읽고 쓰기 관련 공식 문서에서 확인할 수 있습니다.

파일을 열 때 newline=""을 사용해 csv 모듈이 줄바꿈을 처리하게 합니다. Excel 등에서 만든 UTF-8 BOM 파일은 utf-8-sig로 읽으면 첫 열 이름에 BOM 문자가 붙는 문제를 피할 수 있습니다.

전체 예제와 실행 결과

별도의 실습 폴더에서 아래 파일을 UTF-8로 저장합니다. 가상환경을 선택한 터미널에서 python csv_demo.py 명령으로 실행합니다. macOS·Ubuntu에서 가상환경을 사용하지 않는 경우 명령 이름을 python3으로 바꿉니다.

csv_demo.py 파일의 전체 내용입니다.

import csv
from pathlib import Path

path = Path("expenses-demo.csv")
with path.open("w", encoding="utf-8", newline="") as f:
    writer = csv.DictWriter(f, fieldnames=["name", "amount"])
    writer.writeheader()
    writer.writerows([{ "name": "lunch, team", "amount": 8000}, {"name": "bus", "amount": 2500}])
total = 0
with path.open(encoding="utf-8-sig", newline="") as f:
    reader = csv.DictReader(f)
    if reader.fieldnames != ["name", "amount"]:
        raise ValueError("unexpected header")
    for row in reader:
        total += int(row["amount"])
        print(row["name"])
print("total:", total)

예상 결과는 다음과 같습니다.

lunch, team
bus
total: 10500

입력 검증과 출력 형식 정하기

금액에 빈 문자열·천 단위 쉼표·통화 문자가 있으면 int()에 그대로 넣을 수 없습니다. 무작정 모든 문자를 지우면 잘못된 값도 정상처럼 보일 수 있으므로 허용 입력 형식과 오류 기록을 먼저 정합니다.

행 번호를 남기려면 enumerate(reader, start=2)를 사용할 수 있습니다. CSV 필드 안에 줄바꿈이 있으면 논리적 레코드 번호와 실제 파일 줄 번호는 다를 수 있습니다. 무엇을 번호로 표시하는지 설명해야 합니다.

재실행과 스프레드시트에서의 주의점

CSV는 자료형·수식 실행 정책을 포함하지 않는 텍스트입니다. 스프레드시트로 열 때 = 등으로 시작하는 외부 입력이 수식으로 해석될 수 있으므로 공유용 내보내기는 대상 프로그램의 정책에 맞춰 텍스트 처리와 검증을 검토합니다. 따옴표로 감싸기만 하면 모든 수식 위험이 사라진다고 가정하지 않습니다.

  1. 이름 필드에 쉼표가 포함되어도 두 열로 읽히는지 확인합니다.
  2. 헤더 amount를 cost로 바꾸면 검증에서 멈추는지 확인합니다.
  3. 예제는 w 모드로 초기화하므로 재실행해도 행 수가 늘지 않는지 확인합니다.