Модуль csv — работа с CSV-файлами в Python

Формат CSV (Comma Separated Values, «значения, разделённые запятыми») — самый распространённый способ обмена табличными данными между программами: Excel, Google Sheets, базы данных, веб-API экспорта. Если открыть такой файл в текстовом редакторе, мы увидим что-то вроде этого:

id,name,city,age
1,Айдос,Алматы,21
2,Гульнара,Астана,19
3,Ержан,Шымкент,24

Каждая строка — это запись, а поля внутри строки разделены запятой (или другим символом-разделителем — точка с запятой, табуляция и т. д.).

Стандартный модуль Python csv берёт на себя всю чёрную работу: правильно обрабатывает кавычки, экранирование, переводы строк внутри ячеек и разные диалекты CSV. Не пытайтесь парсить CSV через split(',') — это работает только на тепличных данных и ломается при первой же запятой внутри значения.


Зачем нужен модуль csv

CSV выглядит обманчиво простым форматом, но в нём много нюансов:

  • поле может содержать запятую — тогда его берут в кавычки: "Алматы, Казахстан";

  • поле может содержать кавычки — их удваивают: "Он сказал ""привет""";

  • поле может содержать перенос строки;

  • разделителем может быть ;, \t или что угодно ещё (так называемые диалекты).

Модуль csv корректно обрабатывает всё это автоматически. Используйте его всегда, когда работаете с CSV.

Совет

Если данные большие (миллионы строк) или нужны сложные операции (группировка, слияние, агрегаты) — посмотрите в сторону библиотеки pandas. Для простого чтения/записи стандартного csv достаточно и он быстрее по памяти.


Чтение CSV: csv.reader

csv.reader принимает файловый объект и возвращает итератор, который выдаёт каждую строку как список строк.

import csv

with open('users.csv', newline='', encoding='utf-8') as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)

Вывод:

['id', 'name', 'city', 'age']
['1', 'Айдос', 'Алматы', '21']
['2', 'Гульнара', 'Астана', '19']
['3', 'Ержан', 'Шымкент', '24']

Важно

Обратите внимание на newline='' при открытии файла. Это обязательный параметр для csv: без него на Windows можно получить лишние пустые строки между записями.

Часто первая строка — это заголовки. Их можно прочитать отдельно:

import csv

with open('users.csv', newline='', encoding='utf-8') as f:
    reader = csv.reader(f)
    header = next(reader)          # читаем заголовки
    for row in reader:             # дальше идут только данные
        print(dict(zip(header, row)))

Чтение CSV: csv.DictReader

Если заголовки уже есть в файле, удобнее работать со словарями, а не со списками:

import csv

with open('users.csv', newline='', encoding='utf-8') as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(row['name'], '—', row['city'])

Вывод:

Айдос — Алматы
Гульнара — Астана
Ержан — Шымкент

DictReader сам считывает первую строку как заголовки. Если их нет в файле, можно задать вручную:

reader = csv.DictReader(f, fieldnames=['id', 'name', 'city', 'age'])

Запись CSV: csv.writer

Симметрично чтению — csv.writer записывает строки в файл.

import csv

rows = [
    ['id', 'name', 'city'],
    [1, 'Айдос', 'Алматы'],
    [2, 'Гульнара', 'Астана, Казахстан'],   # внутри есть запятая — будет в кавычках
]

with open('out.csv', 'w', newline='', encoding='utf-8') as f:
    writer = csv.writer(f)
    writer.writerows(rows)

Файл out.csv после запуска:

id,name,city
1,Айдос,Алматы
2,Гульнара,"Астана, Казахстан"

Видите — модуль сам поставил кавычки вокруг Астана, Казахстан.


Запись CSV: csv.DictWriter

Для записи словарей:

import csv

rows = [
    {'id': 1, 'name': 'Айдос', 'city': 'Алматы'},
    {'id': 2, 'name': 'Гульнара', 'city': 'Астана'},
]

with open('out.csv', 'w', newline='', encoding='utf-8') as f:
    writer = csv.DictWriter(f, fieldnames=['id', 'name', 'city'])
    writer.writeheader()
    writer.writerows(rows)

Диалекты и параметры

В разных программах CSV формируется немного по-разному. Excel в русской локали, например, использует ; как разделитель, потому что в десятичных числах уже есть запятая. Управлять этим можно через параметры или встроенные диалекты:

reader = csv.reader(f, delimiter=';', quotechar='"')

Самые полезные параметры:

  • delimiter — разделитель полей (по умолчанию ,);

  • quotechar — символ кавычек (по умолчанию ");

  • quoting — стратегия экранирования (csv.QUOTE_ALL, QUOTE_MINIMAL, QUOTE_NONNUMERIC, QUOTE_NONE);

  • escapechar — символ экранирования, если quoting=QUOTE_NONE.

Встроенные диалекты: 'excel' (по умолчанию), 'excel-tab', 'unix'.


Практический пример: фильтрация CSV

Допустим, у нас есть файл orders.csv и нужно выбрать только заказы из Алматы и сохранить в новый файл:

import csv

with open('orders.csv', newline='', encoding='utf-8') as src, \
     open('orders_almaty.csv', 'w', newline='', encoding='utf-8') as dst:

    reader = csv.DictReader(src)
    writer = csv.DictWriter(dst, fieldnames=reader.fieldnames)
    writer.writeheader()

    for row in reader:
        if row['city'] == 'Алматы':
            writer.writerow(row)

Файл читается потоково — даже миллион строк уйдёт без проблем с памятью.


Подводные камни

Предупреждение

  • Кодировка. Файлы из Excel часто сохраняются в cp1251 или utf-8-sig (с BOM в начале). Если получаете UnicodeDecodeError — попробуйте encoding='utf-8-sig' или encoding='cp1251'.

  • Числа остаются строками. csv.reader не угадывает типы: '42' так и останется строкой. Преобразуйте вручную через int(row['age']).

  • ``newline=““`` обязателен — иначе на Windows между строками появятся пустые записи.

  • Размер ячейки. По умолчанию модуль ограничивает поле 128 КБ. Для очень длинных значений вызовите csv.field_size_limit(10**7).


Смотрите также


Примечание

Лицензия и источники

Часть материала адаптирована из официальной документации Python (https://docs.python.org/3/library/csv.html), доступной под Python Software Foundation License Version 2 (PSF License). Адаптация, переработка, оригинальные примеры и пояснения — © AlashEd Wiki.