csv — CSV 파일 읽기와 쓰기

csv — CSV 파일 읽기와 쓰기

csv 모듈은 스프레드시트나 데이터베이스에서 내보낸 표 형식 데이터(CSV, "comma-separated values")를 읽고 쓰는 클래스를 구현해요. CSV 형식 자체는 표준화되지 않았지만, 이 모듈은 다양한 규칙을 수용하도록 견고하고 유연한 인터페이스를 제공합니다.

출처: Python 표준 라이브러리

본문

모듈 함수

csv.reader(csvfile, dialect='excel', **fmtparams)csvfile의 행을 순회하는 리더 객체를 반환해요. csvfile은 문자열이나 숫자 시퀀스를 내놓는 반복 가능한 객체여야 하고, 보통 파일류 객체예요. 읽는 데이터는 문자열로 해석되는데, 다른 형식(예: 숫자)으로 변환하고 싶다면 직접 int()float()를 적용해야 합니다.

csv.writer(csvfile, dialect='excel', **fmtparams)csvfile에 사용자 데이터를 쓰는 라이터 객체를 반환해요. csvfilewrite() 메서드를 가진 파일류 객체여야 하며, 개행 처리를 위해 newline=''으로 열어야 제대로 동작합니다.

import csv
with open('eggs.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    writer.writerow(['Spam', '2', '4.50'])
    writer.writerows([['a', 'b'], ['c', 'd']])

csv.DictReader(f, fieldnames=None, restkey=None, restval=None, dialect='excel', *args, **kwds) — 각 행을 딕셔너리로 매핑하는 객체예요. fieldnames를 지정하지 않으면 첫 번째 행에서 필드 이름을 읽습니다. 행의 열이 필드 이름보다 많으면 남는 값은 restkey 키에 모으고, 부족하면 restval로 채웁니다.

csv.DictWriter(f, fieldnames, restval='', extrasaction='raise', dialect='excel', *args, **kwds) — 각 행을 딕셔너리로부터 쓰는 객체예요. fieldnames에 없는 키가 들어오면 extrasaction 값에 따라 동작하는데, 기본값 'raise'ValueError를, 'ignore'는 무시합니다. writeheader() 메서드로 필드 이름 줄을 쓸 수 있어요.

csv.Sniffer() — 주어진 데이터의 CSV 형식(구분자, 인용 부호 등)을 추측하는 클래스예요. sniff(sample, delimiters=None)로 형식을 알아내고, has_header(sample)로 첫 줄이 헤더인지 추정할 수 있습니다.

dialect과 fmtparams

d리더·라이터는 dialect로 기본 형식을 지정하고, fmtparams 키워드 인자로 개별 설정을 덮어쓸 수 있어요.

csv.list_dialects() — 등록된 모든 dialect 이름을 반환합니다. **csv.get_dialect(name)**는 이름으로 dialect를, **csv.register_dialect(name[, dialect[, **fmtparams]])**는 새 dialect를 등록하고, **csv.unregister_dialect(name)**은 등록을 해제해요.

기본 제공 dialect:

  • csv.excel — Excel이 내보낸 표준 CSV 형식.
  • csv.excel_tab — 탭 문자로 구분된 Excel 형식.
  • csv.unix_dialect — 줄바꿈을 \n으로 쓰는 Unix 스타일.

주요 fmtparams:

  • delimiter — 필드 구분 문자(기본 ,).
  • quotechar — 특수 문자를 감싸는 인용 문자(기본 ").
  • quoting — 인용 규칙. 상수 csv.QUOTE_ALL, QUOTE_MINIMAL(기본), QUOTE_NONNUMERIC, QUOTE_NONE 등.
  • doublequote — 인용 부호 안의 인용 부호를 두 번 써서 표현할지(기본 True).
  • skipinitialspace — 구분자 뒤 공백을 무시할지(기본 False).
  • lineterminator — 행 종결자(리더는 무시, 라이터만 사용, 기본 \r\n)
  • escapecharQUOTE_NONE일 때 특수 문자를 이스케이프하는 문자.
  • strict — 잘못된 입력 시 예외를 일으킬지(기본 False).

Reader/Writer 객체 메서드

csvreader.__next__() — 같은 리더 객체를 호출해 다음 입력 행을 반환해요. 여러 개의 연속된 구분자가 빈 필드를 만들고, 줄바꿈이 있는 필드는 인용 부호로 감싸면 한 필드로 취급됩니다. **csvwriter.writerow(row)**는 한 행을 쓰고, **csvwriter.writerows(rows)**는 여러 행을 씁니다. writer는 dialect 속성으로 사용 중인 형식을 노출해요.

예제

import csv

with open('employee_birthday.txt') as csv_file:
    csv_reader = csv.reader(csv_file, delimiter=',')
    line_count = 0
    for row in csv_reader:
        if line_count == 0:
            print(f'Column names are {", ".join(row)}')
            line_count += 1
        else:
            print(f'\t{row[0]} works in the {row[1]} department, and was born in {row[2]}.')
            line_count += 1
    print(f'Processed {line_count} lines.')

딕셔너리 API로 읽고 쓰는 예:

import csv

with open('names.csv', newline='') as csvfile:
    reader = csv.DictReader(csvfile)
    for row in reader:
        print(row['first_name'], row['last_name'])

주의할 점

CSV 데이터의 구분자가 쉼표가 아닐 수도 있고, 필드 값에 구분자·줄바꿈·인용 부호가 포함될 수 있으므로, 데이터 내용에 따라 적절한 quoting·escapechar 설정을 고려해야 해요. 또 open()을 쓸 때는 텍스트 모드면 newline=''을 지정하는 것이 CSV 모듈 권장 사항입니다.

더 알아보기