Как работать с CSV файлами в Python на примере чтения и записи


04 июня 2021


Работа с CSV файлами в Python их чтение и запись

Один из самых популярных форматов данных является CSV. Для работы с CSV в Python есть несколько библиотек и модулей. С помощью их вы сможете обрабатывать эти данные конвертируя их в словари и списки, создавать файлы и читать их. Основной модуль называется CSV и большинство задач разберем на его примере.

 

Как устроен формат CSV

Основное отличие формата CSV от обычного текста в его структуре, которая проявляется в разделителе. Именно из-за этого этот формат расшифровывается как 'comma separated values' (значения разделенные запятыми). Разделитель не всегда обязан быть в виде запятой, он может принимать и другие виды, например ';'. Разделители так же могут называться делимитер (delimiter). Пример того, как может выглядеть файл:

Имя; Пол; Возраст
Алексей; муж.; 20
Алина; жен.; 21

Первая строка может содержать название заголовки колонок, но это не обязательно. Так же видно, что разделители разделяют значения и из-за этого они не используются в конце строки.

Из-за простого формата CSV вам не обязательно импортировать модули. Вы можете использовать существующий функционал, который создаст данные в формате CSV, например так:

data = [
   ['Имя', 'Пол', 'Возраст'],
   ['Алексей', 'муж.', '20'],
   ['Алина', 'жен.', '21'],
]

csv = ''
for row in data:
   csv += ','.join(row) + '\n'

Конвертация списка в CSV в Python

Тем не менее в модулях реализованы дополнительные возможности по анализу таких данных. Например преобразование в словарь или определение форматов (диалекта).

 

Чтение CSV файлов

Как уже говорилось, основной модуль уже установлен вместе с Python. Для чтения файлов используется функция 'reader()', которая возвращает объект для итерации. Так мы можем открыть файл в большинстве случаев:

import csv

with open('file.csv', 'r') as f:
    data = csv.reader(f)
    for row in data:
        print(row)

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

with open('file.csv', 'r', newline='') as f:

Указание разделителя

По умолчанию считается, что вы используете запятую в качестве делимитра. В моем файле, в качестве разделителя, стоит ';', а файл содержит кириллицу (кириллица имеет значение на Windows). В этом случае файл читается следующим образом:

import csv

with open('file.csv', 'r', encoding='UTF-8') as f:
    data = csv.reader(f, delimiter=';')
    for row in data:
        print(row)

Конвертация в CSV с делиметром в Python

В случае Windows по умолчанию используется кодировка 'cp1251' и, если вы не укажете 'UTF-8', то может появится ошибка:

  • UnicodeDecodeError: 'charmap' codec can't decode byte 0x98 in position 1: character maps to <undefined>

Начальные пробелы

Со скриншота выше видно, что пробелы, в начале строки, не обрабатываются должным образом. Что бы убрать пробелы нужно указать параметр 'skipinitialspace':

import csv

with open('file.csv', 'r', encoding='UTF-8') as f:
    data = csv.reader(f, delimiter=';', skipinitialspace=True)
    for row in data:
        print(row)

Конвертация в CSV с учетом пробелов в Python

Кавычки

CSV файл может содержать кавычки в произвольных местах:

"Name","Age","Sex"
"Alexander Melnikov",45,"m"
"Piter Tolstoy",23,"m"

Убрать их можно используя параметр 'quoting':

import csv

with open('file.csv', 'r') as f:
    data = csv.reader(f, quoting=csv.QUOTE_ALL)
    for row in data:
        print(row)

Конвертация в CSV с учетом кавычек и специальных символов в Python

По умолчанию ищется двойная кавычка. Если вы хотите ее переопределить, то нужно использовать параметр 'quotechar'.

Поиска этой кавычки зависит от того, что указано в параметр 'quoting'. Так значение 'csv.QUOTE_ALL' говорит, что все значения находятся внутри кавычек. Параметр может принимать другие значения:

  • csv.QUOTE_MINIMAL - используется по умолчанию. Кавычки используются в местах содержащие специальные символы (например двойная кавычка из quotechar или сам дилиметр);
  • csv.QUOTE_NONNUMERIC - кавычки используются в нечисловых значениях. Если кавычек в значении не присутствует оно будет преобразовано во float;
  • csv.QUOTE_NONE - кавычки, вокруг значений, не используются.

Если вы установили 'csv.QUOTE_NONE', а в файле все равно экранируются специальные символы, то можно использовать параметр 'escapechar' указывающий на символ экранирования.

Чтение с конвертацией в словарь

Если первая строка у вас содержит заголовки колонок, то вы ее можно преобразовать в ключи словаря. Что бы это сделать, вместо метода 'reader()' используется класс 'DictReader()':

import csv

with open('file.csv', 'r') as f:
    data = csv.DictReader(f, delimiter=';')
    for row in data:
        print(row)

Конвертация словаря в CSV с Python

Тип словаря зависит от версии Python. Если вы используете версию ниже 3.8, то вернется 'OrderedDict', который можно преобразовать в обычный с 'dict()'. В версиях 3.8 и старше возвращается обычный тип словаря.

Параметры у класса аналогичны методу 'reader()'. Мы так же можем определять кавычки и символы экранирования.

Создание шаблона диалекта

Если у вас используется множество разных параметров и идет нарушение принципов DRY (dont repeat yorself), то вы можете использовать диалект (или просто шаблон). В примере мы регистрируем параметры под общим названием 'myDialect' и передаем в функцию или класс:

import csv

csv.register_dialect('myDialect',
                     delimiter=';',
                     skipinitialspace=True,
                     quoting=csv.QUOTE_ALL)

with open('file1.csv', 'r') as f:
    data = csv.reader(f, dialect='myDialect')
    for row in data:
        print(row)

with open('file2.csv', 'r') as f:
    data = csv.reader(f, dialect='myDialect')
    for row in data:
        print(row)

Автоматическое определение параметров CSV файла

Если используются разные файлы CSV и в каждом из них разные параметры для чтения, мы можем определить их автоматически с классом 'Sniffer'. Результат работы этого класса мы можем передать как диалект:

import csv

with open('file.csv', 'r') as f:
    # читаем первые 100 символов (или весь файл)
    sample = f.read(100)    
    # пример проверки, что файл имеет заголовки
    header = csv.Sniffer().has_header(sample)
    print('В файле есть заголовки: ', header)
    # создаем диалект
    dialect = csv.Sniffer().sniff(sample)

with open('file.csv', 'r') as f:
    # передаем диалект и читаем файл
    reader = csv.reader(f, dialect)
    for row in reader:
        print(row)

Определение параметров CSV в Python

Метод 'has_header()' проверяет есть ли в файле заголовки. Аналогично этому методу могут быть использованы и другие методы проверяющие кавычки, делимитры и т.д.

Чтение в pandas

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

import pandas

csv = pandas.read_csv('file.csv', delimiter=';')
print(csv)

Чтение CSV данных с Python и pandas

 

Запись данных в CSV

Для записи данных есть функция 'writer()'. В эту функцию мы можем передать все те же параметры, что в случае чтения. Базовая запись данных будет выглядеть следующим образом:

import csv

lines = [
    ['Alexander Melnikov', '31', 'm'],
    ['Mihail Tolstoy', '28', 'm'],
]

with open('file_w.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    for line in lines:
        writer.writerow(line)
    # или просто
    # writer.writerows(lines)

Запись списка в CSV в Python

Как и понятно с примера выше:

  • writerow - записывает каждый список построчно;
  • writerows - записывает список списков в файл целиком.

Надобность в 'newline' так же может отличаться в разных ОС. Вы можете указать в функции 'writer' параметр 'lineterminator' со значением '\n', который обозначает символ переноса новой строки. По умолчанию он равен '\r\n':

...
with open('file_w.csv', 'w') as f:
    writer = csv.writer(f, lineterminator='\n')
...

Аналогично 'lineterminator' могут передаваться следующие параметры:

  • quotechar - символ для экранирования значений попадающие под условия указанные в 'quoting'. По умолчанию этот символ равен двойным кавычкам;
  • quoting - какие значения должны быть экранированы: csv.QUOTE_MINIMAL (если в значении есть делимитер или сам символ экранирования), csv.QUOTE_ALL (все символы), csv.QUOTE_NONNUMERIC (оборачивает в кавычки все нечисловые значения), csv.QUOTE_NONE (не использует кавычки и, если в значениях используется символ делимитера, экранирует его в 'escapechar');
  • escapechar - если поведение с кавычками не установлено, то символы разделителя в значениях экранируются в этот символ.

Пример использования:

import csv

lines = [
    ['Alexander, Melnikov', '31', 'm'],
    ['Mihail Tolstoy', '28', 'm'],
]

with open('file_w.csv', 'w', newline='') as f:
    writer = csv.writer(f, escapechar='*', quoting=csv.QUOTE_NONE)
    writer.writerows(lines)

Запись списка в CSV в Python с учетом специальных символов и кавычек

Запись словаря

Аналогично чтению мы можем выполнить конвертацию словаря в CSV. Для этого есть класс 'DictWriter'. Запись словаря, от его чтения, отличается параметром 'fieldnames' в котором указываются заголовки колонок. Пример такой записи:

import csv

lines = [
    {'name': 'Alexander Melnikov', 'age': 38, 'sex': 'm'},
    {'name': 'Mihail Tolstoy', 'age': 28, 'sex': 'm'},
]

with open('file_w.csv', 'w', newline='') as f:
    writer = csv.DictWriter(f, fieldnames=['age','sex','name'])
    for line in lines:
        writer.writerow(line)
    # или просто
    # writer.writerows(lines)

Запись словаря в CSV в Python

Параметры, переданные в 'DictWriter', могут быть такими же что и в 'writer'.

Запись с pandas

Что бы сохранить данные с pandas мы сначала должны выполнить конвертацию в 'DataFrame':

import pandas as pd
# словарь
lines1 = [
    {'name': 'Alexander Melnikov', 'age': 38, 'sex': 'm'},
    {'name': 'Mihail Tolstoy', 'age': 28, 'sex': 'm'},
]
# список
lines2 = [
    ['Alexander Melnikov', 38, 'm'],
    ['Mihail Tolstoy', 28, 'm'],
]


lines1 = pd.DataFrame(lines1)
lines2 = pd.DataFrame(lines2)

lines1.to_csv('example1.csv')
lines2.to_csv('example2.csv')

Запись словаря и списка в CSV в Python и pandas

...

Теги: #python #csv


Каналы
Telegram FixMyPc Telegram Лента FixMyPC RSS Rss
Популярные тэги
О блоге
Этот блог представляет собой конспекты выученного материала, приобретённого опыта и лучшие практики в системном администрировании и программировании.