Python csv модуль: практические примеры для табличных данных

Раздел: Обработка данных -> Работа с CSV файлами

Модуль csv в Python предоставляет инструменты для работы с файлами формата CSV (Comma-Separated Values). Этот формат широко используется для хранения табличных данных: каждая строка соответствует одной записи, а колонки разделены определённым символом (обычно запятой). Модуль позволяет гибко настраивать разделители, кавычки и правила экранирования, что делает его незаменимым при обработке данных из различных источников.

Основные приёмы работы с модулем csv

Как прочитать CSV файл с заголовками и получить доступ к данным по имени колонки?

Наиболее эффективным решением является использование класса DictReader. Он автоматически считывает первую строку как заголовки и возвращает каждую последующую строку в виде словаря, где ключи – имена колонок. Это упрощает доступ к данным и делает код читаемым.

import csv

with open('employees.csv', 'r', encoding='utf-8') as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(f"{row['Name']}: {row['Salary']}")

модуль csv в python (модуль csv в python)

Иван: 50000
Мария: 60000

Пример структуры файла employees.csv:

Name,Position,Salary
Иван,Разработчик,50000
Мария,Аналитик,60000

Пояснение: после открытия файла создаётся экземпляр csv.DictReader, который итерируется по строкам. Каждая строка – словарь, ключи которого – значения из первой строки файла. Доступ к полям осуществляется по имени, что удобно при изменении порядка колонок.

Как прочитать CSV файл без заголовков и обращаться к колонкам по индексу?

Для файлов, не содержащих строку заголовков, используется csv.reader. Он возвращает каждую строку как список значений. Порядок колонок фиксирован, и доступ к ним выполняется по индексу.

import csv

with open('data_no_header.csv', 'r', encoding='utf-8') as f:
    reader = csv.reader(f)
    for row in reader:
        print(row[0], row[1])  # первая и вторая колонки
Товар1 100
Товар2 200

Этот вариант подходит, когда структура колонок известна заранее и не планируется менять. Однако при изменении порядка колонок код придётся править.

Типичная ошибка: если в файле используется нестандартный разделитель (например, точка с запятой), по умолчанию csv.reader ожидает запятую. Решение – указать параметр delimiter:

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

Аналогично для DictReader. Также возможна ошибка кодировки – необходимо явно задать encoding.

Как записать данные в CSV файл?

Для записи применяются классы csv.writer и csv.DictWriter. Первый ожидает списки, второй – словари.

import csv

with open('output.csv', 'w', encoding='utf-8', newline='') as f:
    writer = csv.writer(f)
    writer.writerow(['Name', 'Age'])  # заголовок
    writer.writerow(['Анна', 28])
    writer.writerow(['Пётр', 35])

Результат – файл output.csv с двумя строками данных. Параметр newline='' предотвращает добавление лишних пустых строк в Windows.

Для DictWriter необходимо передать список имён полей (fieldnames):

with open('employees_out.csv', 'w', encoding='utf-8', newline='') as f:
    fieldnames = ['Name', 'Position', 'Salary']
    writer = csv.DictWriter(f, fieldnames=fieldnames)
    writer.writeheader()
    writer.writerow({'Name': 'Ольга', 'Position': 'Менеджер', 'Salary': 55000})

Как обработать CSV данные, не сохраняя их в файл (работа со строками)?

Иногда данные поступают в виде строки (например, из веб-запроса). Для таких случаев применяется io.StringIO (или io.BytesIO для бинарных данных).

import csv
import io

csv_data = "Name,Age\nИван,30\nМария,25"
f = io.StringIO(csv_data)
reader = csv.DictReader(f)
for row in reader:
    print(row['Name'], row['Age'])
Иван 30
Мария 25

Этот способ удобен для тестирования или обработки данных, полученных через API.

Как настроить диалект CSV (правила цитирования, разделители)?

Модуль поддерживает предопределённые диалекты (excel, excel-tab, unix) и позволяет создавать собственные с помощью csv.register_dialect.

import csv

csv.register_dialect('mydialect', delimiter='|', quoting=csv.QUOTE_ALL)

with open('pipe_separated.csv', 'r', encoding='utf-8') as f:
    reader = csv.reader(f, dialect='mydialect')
    for row in reader:
        print(row)

Здесь определён диалект с разделителем | и обязательным цитированием всех полей. Это полезно, если формат файла отличается от стандартного.

Типичная ошибка: неправильное указание диалекта может привести к некорректному разбору. Особенно внимательно следует настраивать quotechar (символ кавычки) и escapechar.

Как автоматически определить диалект CSV файла?

Класс csv.Sniffer анализирует образец данных и определяет разделитель, символ кавычек и другие параметры. Это избавляет от ручной настройки при обработке файлов из разных источников.

import csv

with open('unknown.csv', 'r', encoding='utf-8') as f:
    sample = f.read(1024)  # читаем начало файла
    dialect = csv.Sniffer().sniff(sample)
    f.seek(0)
    reader = csv.reader(f, dialect=dialect)
    for row in reader:
        print(row)

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

Как обрабатывать большие CSV файлы, не загружая их целиком в память?

Модуль csv поддерживает итеративный подход: чтение строк по одной. Это позволяет обрабатывать файлы любого размера без переполнения памяти.

import csv

with open('large_data.csv', 'r', encoding='utf-8') as f:
    reader = csv.reader(f)
    next(reader)  # пропустить заголовок
    for row in reader:
        # обработка строки
        process(row)

Аналогично для DictReader. Такой подход эффективен для ETL-процессов и пакетной обработки.

Как обработать строки с пропущенными значениями?

Если в некоторых строках отсутствуют отдельные поля, модуль csv по умолчанию оставляет их пустыми строками. Для DictReader пропущенные поля не включаются в словарь. Чтобы установить значение по умолчанию, можно использовать параметр restval.

import csv

with open('missing.csv', 'r', encoding='utf-8') as f:
    reader = csv.DictReader(f, restval='N/A')
    for row in reader:
        print(row)

Если же файл содержит разное количество полей в строках, поможет csv.reader с проверкой длины списка.

Расширенные примеры использования модуля csv

Пример 1: Чтение CSV с несколькими разделителями и разными типами цитирования

Предположим, файл использует табуляцию как разделитель, а некоторые поля заключены в двойные кавычки. Для работы используется диалект excel-tab.

Пример
import csv

with open('tab_separated.csv', 'r', encoding='utf-8') as f:
    reader = csv.reader(f, dialect='excel-tab')
    for row in reader:
        print(row)
['ID', 'Name', 'Description']
['1', 'Item A', 'Simple item']
['2', 'Item B', 'Complex "description" with quotes']

Обратите внимание: кавычки внутри цитируемого поля экранируются автоматически.

Пример 2: Запись CSV с пользовательским диалектом и нестандартным символом кавычек

Создаётся собственный диалект с апострофом в качестве символа цитирования и разделителем двоеточие.

Пример
import csv

csv.register_dialect('colon', delimiter=':', quotechar="'", quoting=csv.QUOTE_ALL)

with open('custom.csv', 'w', encoding='utf-8', newline='') as f:
    writer = csv.writer(f, dialect='colon')
    writer.writerow(['a', 'b', 'c'])
    writer.writerow([1, 2, 3])

Результат в файле custom.csv:

'a':'b':'c'
'1':'2':'3'

Пример 3: Использование Sniffer для автоматического определения диалекта и разделителя

Функция csv.Sniffer().sniff() возвращает объект диалекта. Дополнительно можно проверить, содержит ли файл заголовок.

Пример
import csv

with open('mixed.csv', 'r', encoding='utf-8') as f:
    sample = f.read(2048)
    dialect = csv.Sniffer().sniff(sample)
    has_header = csv.Sniffer().has_header(sample)
    f.seek(0)
    reader = csv.reader(f, dialect=dialect)
    if has_header:
        header = next(reader)
        print('Заголовок:', header)
    for row in reader:
        print(row)
Заголовок: ['Дата', 'Продажи', 'Комментарий']
['2024-01-01', '100', 'хороший месяц']
['2024-02-01', '150', 'отлично']

Этот пример демонстрирует, как автоматически адаптироваться к различным форматам без ручной настройки.

Пример 4: Обработка CSV с вложенными данными (например, списки внутри поля)

Если одно поле содержит список значений, разделённых точкой с запятой, их можно дополнительно разбить после чтения.

Пример
import csv

with open('nested.csv', 'r', encoding='utf-8') as f:
    reader = csv.DictReader(f)
    for row in reader:
        tags = row['Tags'].split(';')
        print(f"Title: {row['Title']}, Tags: {tags}")
Title: Статья 1, Tags: ['python', 'csv']
Title: Статья 2, Tags: ['data', 'analysis']

Пример 5: Работа с кодировками и большими файлами (построчное чтение с фильтрацией)

При обработке больших файлов важно не накапливать данные в памяти. Ниже показано, как фильтровать строки по условию и записывать результат в новый файл.

Пример
import csv

with open('big_data.csv', 'r', encoding='utf-8') as inf, open('filtered.csv', 'w', encoding='utf-8', newline='') as outf:
    reader = csv.DictReader(inf)
    writer = csv.DictWriter(outf, fieldnames=reader.fieldnames)
    writer.writeheader()
    for row in reader:
        if int(row['Age']) >= 18:
            writer.writerow(row)

Этот код копирует только строки, где возраст не меньше 18, эффективно используя память.

Пример 6: Использование csv.reader со специальными параметрами (escapechar, lineterminator)

Если в данных встречаются символы, совпадающие с разделителем, их можно экранировать обратным слешем.

Пример
import csv

with open('escaped.csv', 'r', encoding='utf-8') as f:
    reader = csv.reader(f, escapechar='\\', quoting=csv.QUOTE_NONE)
    for row in reader:
        print(row)
['a', 'b, c', 'd']
['1', '2', '3']

Здесь запятая внутри поля не считается разделителем, так как перед ней стоит \\. Параметр quoting=csv.QUOTE_NONE отключает цитирование.

Модуль csv в Python - comments

En
модуль csv в python (python)