Модуль csv: чтение и запись таблиц без библиотек

CSV — простейший формат таблиц: строки текста, разделённые запятыми. Встроенный модуль csv читает и пишет его правильно, учитывая кавычки и спецсимволы.
Суть: не парсите CSV через split(',') — запятые внутри значений всё сломают. Используйте модуль csv, а лучше csv.DictReader, который даёт строки как словари.

CSV (comma-separated values) — это таблица в виде текста: первая строка обычно заголовки, дальше — данные, колонки разделены запятыми. Его понимают Excel, Google Sheets и любая база. Поэтому CSV — главный формат обмена табличными данными, и автоматизатор работает с ним постоянно.

Соблазн распарсить CSV «вручную» через line.split(',') велик, но это ловушка. Значение "Иванов, Иван" содержит запятую внутри, и наивный split разорвёт его на две колонки. Модуль csv знает про кавычки и обрабатывает такие случаи правильно.

Модуль csv — часть stdlib и работает в браузере. Прочитаем CSV из строки (как будто из файла) через DictReader.

Попробуй сам ▶

import csv
import io

# CSV как текст; обрати внимание на запятую внутри кавычек
data = '''name,city,sales
"Иванов, И.",Москва,1200
"Петров, П.",Казань,800
"Сидорова, А.",Москва,1500'''

reader = csv.DictReader(io.StringIO(data))
total = 0
for row in reader:
    sales = int(row['sales'])
    total += sales
    print(f"{row['name']:14} {row['city']:8} {sales}")
print('Итого продаж:', total)
# Имя с запятой осталось целым — заслуга модуля csv

DictReader берёт первую строку как заголовки и каждую следующую отдаёт словарём, где ключи — названия колонок. Это намного удобнее, чем обращаться к колонкам по числовому индексу: row['sales'] читается яснее, чем row[2].

ПОТОК ОБРАБОТКИ CSV

  файл.csv
     |  csv.DictReader
     v
  [{name, city, sales}, ...]   строки как словари
     |  фильтр / расчёт
     v
  результат
     |  csv.DictWriter
     v
  отчёт.csv

Запись — зеркальная операция через DictWriter. Этот фрагмент пишет в реальный файл, поэтому показан как нерабочая в браузере врезка.

import csv

rows = [
    {'city': 'Москва', 'total': 2700},
    {'city': 'Казань', 'total': 800},
]
with open('report.csv', 'w', newline='', encoding='utf-8') as f:
    writer = csv.DictWriter(f, fieldnames=['city', 'total'])
    writer.writeheader()
    writer.writerows(rows)

Стоит знать и про разделители: несмотря на название, CSV не всегда использует запятую. В русской локали Excel часто сохраняет файлы с разделителем-точкой-с-запятой, потому что запятая занята под десятичный знак. Модуль csv легко это учитывает — достаточно передать delimiter=';' в reader или writer. Похожая история с кодировкой: файлы из старого Excel могут быть в windows-1251, а не utf-8. Поэтому, открывая чужой CSV, всегда уточняйте, какой разделитель и кодировка в нём приняты — это две самые частые причины, по которым «файл не читается», хотя с кодом всё в порядке.

Как работает под капотом

Модуль csv реализует правила формата RFC 4180: если значение содержит запятую, перевод строки или кавычку, оно оборачивается в двойные кавычки, а кавычки внутри удваиваются. При чтении модуль выполняет обратное — разбирает кавычки и возвращает чистое значение. Именно поэтому он не путается там, где split ломается.

Параметр newline='' при открытии файла — не косметика, а необходимость: он отключает преобразование переводов строк операционной системой, иначе на Windows между строками появятся лишние пустые строки. Это самая частая грабля при записи CSV.

Частые ошибки

  • Парсить через split(','). Ломается на запятых внутри значений и на кавычках.
  • Забыть newline=''. На Windows появляются пустые строки между записями.
  • Игнорировать кодировку. Без encoding='utf-8' кириллица превращается в кракозябры.

Best practices

  • Читайте через DictReader, пишите через DictWriter — код самодокументируется именами колонок.
  • Всегда указывайте encoding='utf-8' и newline=''.
  • Приводите типы явно: из CSV всё приходит строками, число нужно обернуть в int() или float().

Итоги. Модуль csv — правильный способ читать и писать таблицы: DictReader/DictWriter, поддержка кавычек, newline='' и utf-8. Для больших таблиц и сложных расчётов удобнее pandas — им и займёмся дальше.

Проверьте себя
1. Почему нельзя парсить CSV через line.split(',')?
Asplit работает слишком медленно
BЗапятые внутри значений в кавычках разорвут такие поля
Csplit не читает файлы
Dsplit не поддерживает utf-8
2. Что даёт csv.DictReader по сравнению с обычным reader?
AЧитает быстрее
BВозвращает каждую строку словарём с ключами-заголовками
CАвтоматически суммирует колонки
DНе требует открывать файл