Обработка CSV-данных средствами Python
Основы работы с 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.