Обработка CSV-данных средствами Python

Раздел: Работа с файлами -> Работа с CSV-файлами

Основы работы с CSV в Python

Наиболее эффективный способ работы с CSV-файлами в Python - использование встроенного модуля csv. Этот модуль предоставляет классы DictReader и DictWriter, которые автоматически обрабатывают заголовки столбцов, кавычки и различные разделители.

import csv

# Чтение CSV с заголовками
with open('data.csv', newline='', encoding='utf-8') as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(row['name'], row['age'])

Python работа с csv (работа с csv-файлами в python)

Анна 28
Иван 35

Csv формат python (формат csv в python)

Как работает DictReader? Первая строка файла считается заголовком, а последующие строки преобразуются в словари, где ключи - названия столбцов, значения - данные ячеек. Это особенно удобно, когда порядок столбцов может меняться или требуется обращаться к данным по имени.

Частая ошибка: UnicodeDecodeError

Если файл сохранён в кодировке, отличной от UTF-8 (например, Windows-1251), возникает ошибка. Решение - указать правильную кодировку: encoding='cp1251' или использовать utf-8-sig для файлов с BOM.

Для записи CSV используется DictWriter:

import csv

fieldnames = ['name', 'age', 'city']
with open('output.csv', 'w', newline='', encoding='utf-8') as f:
    writer = csv.DictWriter(f, fieldnames=fieldnames)
    writer.writeheader()
    writer.writerow({'name': 'Мария', 'age': 22, 'city': 'Москва'})

Python читаем csv (чтение csv-файла в python)

Этот подход гарантирует соответствие порядка столбцов заданному списку и автоматически экранирует специальные символы.

Как прочитать CSV без заголовков с помощью reader?

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

import csv

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

Python создать csv (создание csv-файла в python)

Цель: быстрый доступ к данным по индексу столбца. Минус - код становится менее читаемым при большом количестве столбцов.

Проблема: пропущенные значения

Если в ячейке пусто, reader вернёт пустую строку. Это может привести к неожиданному сдвигу индексов при дальнейшей обработке. Рекомендуется проверять длину строки или использовать значения по умолчанию.

Как обработать CSV с большим объёмом данных с помощью Pandas?

Для анализа данных с тысячами строк и столбцов удобна библиотека Pandas. Она загружает CSV в DataFrame и предоставляет мощные инструменты фильтрации, группировки и визуализации.

import pandas as pd

df = pd.read_csv('bigdata.csv', encoding='utf-8')
print(df.describe())
print(df['salary'].mean())

Случай использования: статистическая обработка, очистка данных, работа с пропусками (NaN). Pandas автоматически определяет типы данных, но для больших файлов потребуется больше памяти.

Типичная ошибка: MemoryError

При загрузке файла размером больше доступной оперативной памяти программа завершается с ошибкой. Решение - читать данные порциями через параметр chunksize.

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

Модуль csv также предоставляет класс writer для записи данных из списков. Это быстрее, чем DictWriter, но требует ручного управления порядком столбцов.

import csv

rows = [
    ['Товар', 'Цена', 'Количество'],
    ['Книга', 450, 10],
    ['Ручка', 30, 50]
]
with open('products.csv', 'w', newline='', encoding='utf-8') as f:
    writer = csv.writer(f)
    writer.writerows(rows)

Этот вариант подходит для быстрой записи заранее сформированных таблиц.

Как прочитать CSV с разделителем-табуляцией?

По умолчанию модуль csv использует запятую как разделитель. Для табуляции, точки с запятой или другого символа передаётся параметр delimiter.

import csv

with open('tab_data.tsv', newline='', encoding='utf-8') as f:
    reader = csv.reader(f, delimiter='\t')
    for row in reader:
        print(row)

Аналогично для записи: writer = csv.writer(f, delimiter='|').

Проблема: некорректное экранирование

При использовании нестандартных разделителей могут возникнуть проблемы с кавычками. Рекомендуется также задать quoting (например, csv.QUOTE_NONNUMERIC).

Что делать при UnicodeDecodeError?

Ошибка возникает, когда кодировка файла не совпадает с указанной в open. Способы решения:

  • Определить кодировку с помощью chardet или codecs
  • Использовать универсальную кодировку utf-8-sig
  • Попробовать latin-1 (не теряет данные, но может дать кракозябры)
import chardet

with open('unknown.csv', 'rb') as f:
    raw = f.read(10000)
    result = chardet.detect(raw)
    print(result['encoding'])  # например cp1251

После этого открыть файл с определённой кодировкой.

Как игнорировать пустые строки в CSV?

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

with open('data.csv') as f:
    reader = csv.reader(f)
    for row in reader:
        if row:  # пропускаем пустые строки
            process(row)

Для DictReader можно проверять, есть ли хотя бы один непустой заголовок.

Как прочитать CSV из сжатого gzip архива?

Большие CSV-файлы часто хранятся в сжатом виде. Используется модуль gzip в паре с csv.

import gzip
import csv

with gzip.open('data.csv.gz', 'rt', newline='', encoding='utf-8') as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(row)

Режим 'rt' открывает текстовый поток, необходимый для csv.reader. Аналогично для записи.

Как записать CSV с дополнительными параметрами (quoting, delimiter)?

Иногда требуется экранировать все значения (QUOTE_ALL) или только нечисловые (QUOTE_NONNUMERIC).

import csv

with open('quoted.csv', 'w', newline='') as f:
    writer = csv.writer(f, delimiter=';', quoting=csv.QUOTE_ALL)
    writer.writerow(['Имя', 'Возраст'])
    writer.writerow(['Анна', 28])

Результат: "Имя";"Возраст" и "Анна";"28" (число также заключено в кавычки).

Расширенные примеры работы с CSV

Пример 1: чтение CSV с преобразованием типов и обработкой дат

Предположим, CSV содержит столбцы 'date', 'value' (число) и 'description'. Необходимо преобразовать строку даты в объект datetime и значение в float.

Пример
import csv
from datetime import datetime

filename = 'transactions.csv'
# Содержимое файла:
# date,value,description
# 2024-01-15,123.45,Оплата услуг
# 2024-02-20,67.0,Возврат

with open(filename, newline='', encoding='utf-8') as f:
    reader = csv.DictReader(f)
    for row in reader:
        try:
            row['date'] = datetime.strptime(row['date'], '%Y-%m-%d')
            row['value'] = float(row['value'])
            print(f"{row['date'].strftime('%d.%m.%Y')}: {row['value']} - {row['description']}")
        except ValueError as e:
            print(f"Ошибка в строке: {e}")
15.01.2024: 123.45 - Оплата услуг
20.02.2024: 67.0 - Возврат

Особенность: обработка ошибок важна, так как данные могут быть некорректными. В реальном проекте можно логировать проблемные строки.

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

Необходимо создать файл с разделителем точка с запятой, заголовки формируются на основе ключей первого словаря. Используется DictWriter с автоматической записью заголовков.

Пример
import csv

data = [
    {'product': 'Молоко', 'price': 89.5, 'quantity': 2},
    {'product': 'Хлеб', 'price': 45.0, 'quantity': 1}
]

with open('order.csv', 'w', newline='', encoding='utf-8') as f:
    fieldnames = data[0].keys()  # заголовки из первого элемента
    writer = csv.DictWriter(f, fieldnames=fieldnames, delimiter=';',
                            quoting=csv.QUOTE_NONNUMERIC)
    writer.writeheader()
    for item in data:
        writer.writerow(item)
# Содержимое order.csv:
"product";"price";"quantity"
"Молоко";89.5;2
"Хлеб";45.0;1

Числовые столбцы не заключаются в кавычки благодаря QUOTE_NONNUMERIC.

Пример 3: автоматическое определение формата CSV с помощью Sniffer

Если формат CSV неизвестен (разделитель, кавычки), класс csv.Sniffer анализирует образец файла и определяет диалект.

Пример
import csv

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

Sniffer может определить разделитель, символ кавычки, escape-символ. Осторожно: для очень коротких или нестандартных файлов результат может быть неточным.

Пример 4: параллельная обработка большого CSV с использованием multiprocessing

Для ускорения обработки большого файла его можно разбить на части и обрабатывать параллельно. В примере используется пул процессов.

Пример
import csv
import multiprocessing
from itertools import islice

def process_chunk(chunk):
    # chunk - список строк, каждая строка - список полей
    result = []
    for row in chunk:
        if row:  # непустая строка
            # например, извлечение первой буквы
            result.append((row[0], len(row)))
    return result

filename = 'large.csv'
chunk_size = 10000

with open(filename, newline='', encoding='utf-8') as f:
    reader = csv.reader(f)
    # Пропускаем заголовок, если он есть
    header = next(reader, None)
    chunks = []
    while True:
        chunk = list(islice(reader, chunk_size))
        if not chunk:
            break
        chunks.append(chunk)

with multiprocessing.Pool() as pool:
    results = pool.map(process_chunk, chunks)

# Объединение результатов
all_rows = [item for sublist in results for item in sublist]
print(f"Обработано {len(all_rows)} строк")
Обработано 123456 строк

Замечание: данный подход эффективен для CPU-интенсивных операций. Для IO-bound задач лучше использовать асинхронное чтение.

Пример 5: преобразование CSV в JSON с кастомными ключами

Иногда требуется сохранить данные CSV в формате JSON, изменив названия полей или добавив вложенные структуры.

Пример
import csv
import json

csv_data = """name,age,city
Иван,30,Москва
Анна,25,Санкт-Петербург
"""

reader = csv.DictReader(csv_data.splitlines())
output = []
for row in reader:
    new_record = {
        'full_name': row['name'],
        'years_old': int(row['age']),
        'location': row['city']
    }
    output.append(new_record)

print(json.dumps(output, ensure_ascii=False, indent=2))
[
  {
    "full_name": "Иван",
    "years_old": 30,
    "location": "Москва"
  },
  {
    "full_name": "Анна",
    "years_old": 25,
    "location": "Санкт-Петербург"
  }
]

Метод splitlines() создаёт список строк из текстовой переменной, имитируя файл. Для реального файла используется open.

Работа с CSV-файлами в Python - comments

En
Python работа с csv (python)