Работа с CSV в Python

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

Файлы CSV

Файл CSV (значения, разделённые запятыми) является по сути текстовым файлам, данные в котором разделены с помощью специального разделителя. В качестве разделителя обычно используется запятая или символ «;», но могут использоваться и другие разделители. Каждая новая запись в файле CSV начинается с новой строки.

Формат файлов CSV можно легко экспортировать в электронные таблицы или базы данных.

Пример CSV файла, где разделителем используется «;»:

Фамилия; Имя; Отчество; Место работы; Год рождения
Сидоров; Иван; Петрович; Нижний Тагил; 1995
Загоруля; Петр; Иванович; Нижний Тагил; 1974
import csv
with open("file.csv", encoding='utf-8') as file:

    csvfilereader = csv.reader(file, delimiter=";")

    # Счетчик

    i = 0

    for r in csvfilereader:

        # Для заголовков

        if i == 0:

            print(f'Файл содержит столбцы: {";".join(r)}')

        # Для строк

        else:

            print(f'{r[0]} {r[1]} {r[2]} - {r[3]} 

                  f'родился в городе {r[4]}.')

        i += 1

print(f'В файле {i} строк.')

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

Разделителем может выступать любой другой символ, поэтому очень важно при чтении CSV файла заранее знать какой символ используется в качестве разделителя. Файл CSV – это по сути обычный текстовый файл, который не поддерживает символы в кодировках, отличающихся от ASCII или Unicode.

Библиотека CSV

Эта библиотека является встроенной, и её не нужно дополнительно скачивать через систему управления пакетами pip. Эта библиотека является основной для работы с файлами CSV в Python. Она импортируется как обычные встроенные библиотеки:

import csv

Чтение и парсинг файлов

Чтобы прочитать файл csv, необходимо создать объект reader:

object = csv.reader(data, delimiter = ";")

Объект reader имеет метод __next__(), и является итерируемым объектом.
Чтение файла будет происходить так:

import csv

with open("file.csv", encoding='utf-8') as file:

    csvfilereader = csv.reader(file, delimiter=";")

    # Счетчик

    i = 0

    for r in csvfilereader:

        # Для заголовков

        if i == 0:

            print(f'Файл содержит столбцы: {";".join(r)}')

        # Для строк

        else:

            print(f'{r[0]} {r[1]} {r[2]}-{r[3]} родился в городе {r[4]}.')

        i += 1

    print(f'В файле {i} строк.')

Допустим, у нас есть CSV файл, который содержит следующую информацию:

Фамилия, Имя, Отчество, Оценка, Место рождения
Сидоров, Иван, Иванович, 3, Москва
Зубрило, Антон, Николаевич, 4, Севастополь
Петров, Борис, Захарович, 5, Курск

Если запустить данный код в интерпретаторе, то получим следующее:

Файл содержит столбцы: Фамилия, Имя, Отчество, Оценка, Место рождения
    Сидоров Иван Иванович - 3 родился в городе Москва.
    Иванова Екатерина Анатольевна - 3 родился в городе Севастополь.
    Петров Борис Захарович - 4 родился в городе Курск.
В файле 4 строк.

Конструкция with…as используется для того, чтобы быть уверенным, что файл будет корректно закрыт в случае если при выполнении программного кода произойдет непредвиденная ошибка.

Стоит уделить внимание на то, что если перед чтением файла принудительно не установить правильную кодировку, в которой ранее файл был сохранен в нашем случае «UTF-8», то будет использоваться кодировка, определенная по умолчанию. Для windows это cp1251.

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

import csv

with open("file.csv", encoding='utf-8') as file:

    CsvDictReader = csv.DictReader(file, delimiter=";")

    # Счетчик

    i = 0

    for r in CsvDictReader:

        # Для заголовков

        if i == 0:

            print(f'Файл содержит столбцы: {";".join(r)}')

        # Для строк

        print(f' {r["Фамилия"]} {r["Имя"]} {r["Отчество"]} - {r["Оценка"]}'

              f' родился в городе {r["Место рождения"]}.')

        i += 1

    print(f'В файле {i} строк.')

Обращение к элементам по названию упрощает понимание кода, к тому же так более удобно.

При использовании DictReader в первой строке цикла будет содержаться не заголовок таблицы, а первая строка с данными. Поэтому для вывода заголовка используется условие i==0.

Дополнительные параметры объекта DictReader

DictReader имеет параметры:

  • fieldnames– Определяет заголовки для столбцов;
  • dialect– Параметры для форматирования информации. Ниже будут описаны подробности;
  • line_num– Устанавливает лимит на количество строк, которое может быть прочитано.

Например, если бы файл file.csv не содержал первую строку с заголовками, то можно было бы его открыть следующим образом:

heading = [‘Фамилия’, ‘Имя’, ‘Отчество’, ‘Оценка’, ‘Место рождения’]

object = csv.DictReader(file, fieldnames = heading)

Если не определить атрибут, то в него запишутся элементы из первой прочитанной строки файла. Заголовки можно и не задавать, но файл содержащий заголовки будет более понятен.

Запись в CSV

Для записи информации с CSV файл нужно использовать специальный объект writer.

w = csv.writer(file, delimiter = "\t")

Запись новой строки в файл осуществляется с помощью метода writerow(). Этот метод имеет следующий синтаксис:

writerow("Имя", "Пол", "Возраст")

Пример программы с использованием метода writerow():

import csv

with open("file.csv", mode="w", encoding='utf-8') as file:

    w = csv.writer(file, delimiter = ",", lineterminator="\r")

    w.writerow(["Имя", "Пол", "Возраст"])

    w.writerow(["Даша", "Женский", "7"])

    w.writerow(["Степа", "Мужской", "14"])

    w.writerow(["Иван", "Мужской", "16"])

В данном примере в качестве разделителей значений используется «;». Для разделения строк таблицы по умолчанию это параметр lineterminator со значением \r\n. В нашем примере мы использовали просто \r

После выполнения этого фрагмента кода, в файл CSV будет записаны следующие данные:

Имя, Пол, Возраст
Даша, Женский, 7
Степа, Мужской, 14
Иван, Мужской, 16

В метод writerow() необходимо передавать список, который в последствии будет записан в файл через симол-разделитель.

Запись в файл также может быть осуществлена с помощью объекта DictWriter.

Метод DictWriter требует строгого указания параметра fieldnames. В качестве данных для записи используется словарь.

Пример программы выглядит так:

import csv

with open("file.csv", mode="w", encoding='utf-8') as file:

    names = ["Фамилия", "Имя"]

    w = csv.DictWriter(file, delimiter = ",",lineterminator="\r", fieldnames=names)

    w.writeheader()

    w.writerow({"Фамилия": "Зимина", "Имя": "Надя"})

    w.writerow({"Фамилия": "Сидорова", "Имя": "Маша"})

    w.writerow({"Фамилия": "Петров", "Имя": "Вова"})

Результат, который будет записан в файл будет следующим:

Фамилия, Имя
Зимина, Надя
Сидорова, Маша
Петров, Вова

В примере приведенном выше, использовался метод
writeheader(). Этот метод записывает заголовки для столбцов. Заголовки должны быть переданы объекту writer в виде списка по аналогии с атрибутом fieldnames.

Объект DictWriter также имеет еще один замечательный метод:

  • writerows(rows) – Записывает все элементы строк.

Ниже приведен листинг кода использующий этот метод. Рассмотрим пример кода с использованием метода writerows:

writer.writerows([{"Фамилия": "Зимина", "Имя": "Надя"},

{"Фамилия": "Сидорова", "Имя": "Маша"},

{"Фамилия": "Петров", "Имя": "Вова"}])

Объект writer имеет атрибут dialect, который определяет, как будут отформатированы данные при записи в файл.

Диалекты

Форматы входных и выходных данных могут быть сгруппированы в диалекты (dialect). При создании объектов reader или writer можно назначить нужный диалект, также можно переопределить диалект вручную, указав их при создании объекта.

Для инициализации диалекта используется команда:

csv.register_dialect("имя", delimiter = ",", ...)

Возможно использовать следующие атрибуты для указания форматирования:

  • Delimiter – Задает символ, который будет разделять элементы в файле. Запятая используется по умолчанию.
  • Doublequote — Если False, то к символу qutechar добавляется ecsapechar в качестве префикса, если True, то символ quotechar удваивается.
  • Escapechar – Использует один символ, для экранирования символа-разделителя.
  • Lineterminator — Определяет разделитель для строк, по умолчанию используется “\r\n”
  • Quotechar — Определяет символ, который используется для окружения символа-разделителя. По умолчанию используются двойные кавычки, то есть quotechar = ‘»’
  • Quoting – если не используются кавычки, то определяет символ, который используется для экранирования символа разделителя.
  • Skipinitialspace – При установке в true, то все пробелы после символа-разделителя будут игнорироваться.
  • Strict – если установить true, то в случае некорректно сформированного файла CSV будет вызвано исключение Error

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

<pre>import csv

csv.register_dialect('my_di', delimiter=':', lineterminator="\r")

with open("file.csv", mode="w", encoding='utf-8') as file:

    w = csv.writer(file, 'my_di')

    w.writerow(["Фамилия", "Имя", "Пол"])

    w.writerow(["Зимина", "Надя", "Женский"])

    w.writerow(["Сидорова", "Маша", "Женский"])

    w.writerow(["Петров", "Вова", "Мужской"])</pre>

В результате получим:

Фамилия:Имя:Пол
Зимина:Надя:Женский
Сидорова:Маша:Женский
Петров:Вова:Мужской