Python 강좌 / CSV 파일 읽고 쓰기

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

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

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

관련 동작과 지원 조건은 Python: csv에서 확인할 수 있습니다.

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

CSV 검증과 분석 단계은 종합 실습: CSV 데이터를 검증하고 보고서 만들기에서 사용하는 규칙과 연결됩니다.

전체 예제와 실행 결과

별도의 실습 폴더에서 아래 파일을 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 필드 안에 줄바꿈이 있으면 논리적 레코드 번호와 실제 파일 줄 번호는 다를 수 있습니다. 무엇을 번호로 표시하는지 설명해야 합니다.

쉼표가 포함된 필드 "coffee, large"는 CSV에서 하나의 필드입니다. csv.reader는 이를 문자열 하나로 복원하지만 split은 두 조각으로 나눕니다. 저장 결과를 텍스트로 열어 따옴표를 확인하고, 다시 csv.reader로 읽어 필드 개수와 원래 값이 같은지 확인합니다. 화면에 쉼표가 보이는 것만으로 열이 추가되었다고 판단하지 않습니다.

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

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

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