Содержание страницы
13.1. csv– чтение и запись CSV-файлов¶csv – CSV File Reading and Writing
Новое в версии 2.3.
Так называемый формат CSV (Comma Separated Values – значения, разделённые запятыми) – наиболее распространённый формат импорта и экспорта электронных таблиц и баз данных. Не существует «стандарта CSV», поэтому формат определяется операционно, на основе множества приложений, которые его читают и записывают. Отсутствие стандарта означает, что в данных, создаваемых и потребляемых разными приложениями, часто существуют тонкие различия. Эти различия могут затруднять обработку CSV-файлов из нескольких источников. Тем не менее, хотя разделители и символы кавычек различаются, общий формат достаточно схож, чтобы можно было написать единый модуль, способный эффективно манипулировать такими данными, скрывая от программиста детали чтения и записи.
Модуль csv реализует классы для чтения и записи табличных данных в формате CSV. Он позволяет программистам сказать: «запиши эти данные в формате, предпочитаемом Excel» или «прочитай данные из этого файла, созданного Excel», не вдаваясь в точные детали формата CSV, используемого Excel. Программисты также могут описывать форматы CSV, используемые другими приложениями, или определять собственные специализированные форматы CSV.
Объекты reader и writer модуля csv читают и записывают последовательности. Программисты также могут читать и записывать данные в словарной форме, используя классы DictReader и DictWriter.
Примечание
Эта версия модуля csv не поддерживает ввод Unicode. Кроме того, в настоящее время есть некоторые проблемы с символами ASCII NUL. Поэтому весь ввод должен быть в UTF-8 или в печатаемом ASCII для безопасности; см. примеры в разделе Примеры.
См. также
- PEP 305 - API для CSV-файлов
Предложение по улучшению Python, в котором было предложено это дополнение.
13.1.1. Содержание модуля¶Module Contents
Модуль csv определяет следующие функции:
-
csv.reader(csvfile, dialect='excel', **fmtparams)¶ Возвращает объект чтения (reader), который будет выполнять итерацию по строкам в заданном csvfile. csvfile может быть любым объектом, поддерживающим протокол итератора и возвращающим строку при каждом вызове метода
next()– подходят как файловые объекты, так и списки. Если csvfile является файловым объектом, он должен быть открыт с флагом 'b' на платформах, где это имеет значение. Можно задать необязательный параметр dialect, который используется для определения набора параметров, специфичных для конкретного диалекта CSV. Это может быть экземпляр подкласса классаDialectили одна из строк, возвращаемых функциейlist_dialects(). Другие необязательные именованные аргументы fmtparams можно задать для переопределения отдельных параметров форматирования в текущем диалекте. Полные сведения о диалекте и параметрах форматирования см. в разделе Диалекты и параметры форматирования.Каждая строка, прочитанная из CSV-файла, возвращается в виде списка строк. Автоматическое преобразование типов данных не выполняется.
Краткий пример использования:
>>> import csv >>> with open('eggs.csv', 'rb') as csvfile: ... spamreader = csv.reader(csvfile, delimiter=' ', quotechar='|') ... for row in spamreader: ... print ', '.join(row) Spam, Spam, Spam, Spam, Spam, Baked Beans Spam, Lovely Spam, Wonderful Spam
Изменено в версии 2.5: Теперь анализатор стал строже в отношении многострочных полей в кавычках. Ранее, если строка заканчивалась внутри поля в кавычках без завершающего символа новой строки, в возвращаемое поле вставлялся символ новой строки. Это поведение вызывало проблемы при чтении файлов, содержащих символы возврата каретки внутри полей. Поведение было изменено: теперь поле возвращается без вставки новых строк. Как следствие, если встроенные в поля символы новой строки важны, входные данные следует разбивать на строки таким образом, чтобы сохранить символы новой строки.
-
csv.writer(csvfile, dialect='excel', **fmtparams)¶ Возвращает объект записи (writer), отвечающий за преобразование пользовательских данных в строки с разделителями для заданного файлоподобного объекта. csvfile может быть любым объектом с методом
write(). Если csvfile является файловым объектом, он должен быть открыт с флагом 'b' на платформах, где это имеет значение. Можно задать необязательный параметр dialect, который используется для определения набора параметров, специфичных для конкретного диалекта CSV. Это может быть экземпляр подкласса классаDialectили одна из строк, возвращаемых функциейlist_dialects(). Другие необязательные именованные аргументы fmtparams можно задать для переопределения отдельных параметров форматирования в текущем диалекте. Полные сведения о диалекте и параметрах форматирования см. в разделе Диалекты и параметры форматирования. Чтобы максимально упростить взаимодействие с модулями, реализующими DB API, значениеNoneзаписывается как пустая строка. Хотя это не является обратимым преобразованием, это упрощает выгрузку значений SQL NULL в CSV-файлы без предварительной обработки данных, возвращаемых вызовомcursor.fetch*. Числа с плавающей точкой преобразуются в строку с помощьюrepr()перед записью. Все остальные нестроковые данные преобразуются в строку с помощьюstr()перед записью.Краткий пример использования:
import csv with open('eggs.csv', 'wb') as csvfile: spamwriter = csv.writer(csvfile, delimiter=' ', quotechar='|', quoting=csv.QUOTE_MINIMAL) spamwriter.writerow(['Spam'] * 5 + ['Baked Beans']) spamwriter.writerow(['Spam', 'Lovely Spam', 'Wonderful Spam'])
-
csv.register_dialect(name, [dialect, ]**fmtparams)¶ Связывает dialect с name. name должен быть строкой или объектом Unicode. Диалект можно задать, передав подкласс
Dialect, или с помощью именованных аргументов fmtparams, или обоими способами, при этом именованные аргументы переопределяют параметры диалекта. Полные сведения о диалекте и параметрах форматирования см. в разделе Диалекты и параметры форматирования.
-
csv.unregister_dialect(name)¶ Удаляет диалект, связанный с name, из реестра диалектов. Возникает исключение
Error, если name не является зарегистрированным именем диалекта.
-
csv.get_dialect(name)¶ Возвращает диалект, связанный с name. Если name не является зарегистрированным именем диалекта, вызывается исключение
Error.Изменено в версии 2.5: Теперь эта функция возвращает неизменяемый
Dialect. Ранее возвращался экземпляр запрошенного диалекта. Пользователи могли изменять базовый класс, меняя поведение активных читателей и писателей.
-
csv.list_dialects()¶ Возвращает имена всех зарегистрированных диалектов.
-
csv.field_size_limit([new_limit])¶ Возвращает текущий максимальный размер поля, разрешенный парсером. Если задан new_limit, он становится новым лимитом.
Новое в версии 2.5.
Модуль csv определяет следующие классы:
-
class
csv.DictReader(f, fieldnames=None, restkey=None, restval=None, dialect='excel', *args, **kwds)¶ Создаёт объект, который работает как обычный читатель, но преобразует прочитанную информацию в словарь, ключи которого задаются необязательным параметром fieldnames. Параметр fieldnames представляет собой последовательность, элементы которой последовательно связываются с полями входных данных. Эти элементы становятся ключами результирующего словаря. Если параметр fieldnames опущен, в качестве имён полей используются значения первой строки файла f. Если прочитанная строка содержит больше полей, чем последовательность имён полей, оставшиеся данные добавляются в виде последовательности, ключом которой является значение restkey. Если прочитанная строка содержит меньше полей, чем последовательность имён полей, оставшиеся ключи принимают значение необязательного параметра restval. Любые другие необязательные или именованные аргументы передаются базовому экземпляру
reader.Краткий пример использования:
>>> import csv >>> with open('names.csv') as csvfile: ... reader = csv.DictReader(csvfile) ... for row in reader: ... print(row['first_name'], row['last_name']) ... Baked Beans Lovely Spam Wonderful Spam
-
class
csv.DictWriter(f, fieldnames, restval='', extrasaction='raise', dialect='excel', *args, **kwds)¶ Создаёт объект, который работает как обычный писатель, но преобразует словари в строки вывода. Параметр fieldnames представляет собой последовательность ключей, определяющих порядок, в котором значения из словаря, переданного методу
writerow(), записываются в файл f. Необязательный параметр restval задаёт значение, которое будет записано, если в словаре отсутствует ключ из fieldnames. Если словарь, переданный методуwriterow(), содержит ключ, отсутствующий в fieldnames, необязательный параметр extrasaction указывает, какое действие предпринять. Если он установлен в'raise', вызывается исключениеValueError. Если он установлен в'ignore', дополнительные значения в словаре игнорируются. Любые другие необязательные или именованные аргументы передаются базовому экземпляруwriter.Обратите внимание, что, в отличие от класса
DictReader, параметр fieldnames классаDictWriterне является необязательным. Поскольку объектыdictв Python не упорядочены, недостаточно информации, чтобы определить порядок, в котором строка должна быть записана в файл f.Краткий пример использования:
import csv with open('names.csv', 'w') as csvfile: fieldnames = ['first_name', 'last_name'] writer = csv.DictWriter(csvfile, fieldnames=fieldnames) writer.writeheader() writer.writerow({'first_name': 'Baked', 'last_name': 'Beans'}) writer.writerow({'first_name': 'Lovely', 'last_name': 'Spam'}) writer.writerow({'first_name': 'Wonderful', 'last_name': 'Spam'})
-
class
csv.Dialect¶ Класс
Dialect– это контейнерный класс, используемый в первую очередь для своих атрибутов, которые задают параметры для конкретного экземпляраreaderилиwriter.
-
class
csv.excel¶ Класс
excelопределяет обычные свойства CSV-файла, созданного в Excel. Он зарегистрирован под именем диалекта'excel'.
-
class
csv.excel_tab¶ Класс
excel_tabопределяет обычные свойства файла с разделителями табуляции, созданного в Excel. Он зарегистрирован под именем диалекта'excel-tab'.
-
class
csv.Sniffer¶ Класс
Snifferиспользуется для определения формата CSV-файла.Класс
Snifferпредоставляет два метода:
Пример использования Sniffer:
with open('example.csv', 'rb') as csvfile:
dialect = csv.Sniffer().sniff(csvfile.read(1024))
csvfile.seek(0)
reader = csv.reader(csvfile, dialect)
# ... здесь обрабатывается содержимое CSV-файла ...
Модуль csv определяет следующие константы:
-
csv.QUOTE_MINIMAL¶ Указывает объектам
writerзаключать в кавычки только те поля, которые содержат специальные символы, такие как разделитель, символ кавычки или любой из символов терминатора строки.
-
csv.QUOTE_NONNUMERIC¶ Указывает объектам
writerзаключать все нечисловые поля в кавычки.Указывает объекту чтения преобразовывать все нецитируемые поля в тип float.
-
csv.QUOTE_NONE¶ Указывает объектам
writerникогда не заключать поля в кавычки. Если текущий разделитель встречается в выходных данных, перед ним ставится текущий символ escapechar. Если escapechar не задан, объект writer вызоветError, если встретятся символы, требующие экранирования.Указывает
readerне выполнять специальной обработки символов кавычек.
Модуль csv определяет следующее исключение:
-
exception
csv.Error¶ Возбуждается любой из функций при обнаружении ошибки.
13.1.2. Диалекты и параметры форматирования¶Dialects and Formatting Parameters
Чтобы упростить задание формата входных и выходных записей, определённые
параметры форматирования группируются в диалекты. Диалект – это подкласс класса Dialect, имеющий набор определённых методов и единственный метод validate(). При создании объектов reader или writer программист может указать в качестве параметра dialect строку или подкласс класса Dialect. В дополнение к параметру dialect или вместо него программист может также указать отдельные
параметры форматирования, имена которых совпадают с атрибутами класса Dialect, определёнными ниже.
Диалекты поддерживают следующие атрибуты:
-
Dialect.delimiter¶ Односимвольная строка, используемая для разделения полей. По умолчанию равна
','.
-
Dialect.doublequote¶ Управляет тем, как должны заключаться в кавычки экземпляры quotechar, встречающиеся внутри поля. Когда
True, символ удваивается. КогдаFalse, escapechar используется в качестве префикса для quotechar. По умолчаниюTrue.При выводе, если doublequote равно
Falseи escapechar не задан, возбуждаетсяError, если в поле обнаружен quotechar.
-
Dialect.escapechar¶ Односимвольная строка, используемая объектом writer для экранирования разделителя, если для quoting установлено значение
QUOTE_NONE, и quotechar, если doublequote равноFalse. При чтении escapechar снимает особое значение со следующего символа. По умолчаниюNone, что отключает экранирование.
-
Dialect.lineterminator¶ Строка, используемая для завершения строк, создаваемых
writer. По умолчанию равна'\r\n'.Примечание
Модуль
readerжёстко запрограммирован распознавать'\r'или'\n'как конец строки и игнорировать lineterminator. В будущем это поведение может измениться.
-
Dialect.quotechar¶ Односимвольная строка, используемая для заключения в кавычки полей, содержащих специальные символы, такие как разделитель или quotechar, или содержащих символы новой строки. По умолчанию
'"'.
-
Dialect.quoting¶ Управляет тем, когда кавычки должны генерироваться писателем (writer) и распознаваться читателем (reader). Может принимать любое из значений констант
QUOTE_*(см. раздел Содержание модуля); по умолчаниюQUOTE_MINIMAL.
13.1.3. Объекты Reader¶Reader Objects
Объекты reader (экземпляры DictReader и объекты, возвращаемые функцией reader()) имеют следующие открытые методы:
-
csvreader.next()¶ Возвращает следующую строку итерируемого объекта reader в виде списка, разобранную в соответствии с текущим диалектом.
Объекты reader имеют следующие открытые атрибуты:
-
csvreader.dialect¶ Доступное только для чтения описание диалекта, используемого синтаксическим анализатором.
-
csvreader.line_num¶ Количество строк, прочитанных из итератора-источника. Это число не совпадает с количеством возвращённых записей, так как записи могут занимать несколько строк.
Новое в версии 2.5.
Объекты DictReader имеют следующий открытый атрибут:
-
csvreader.fieldnames¶ Если этот атрибут не был передан в качестве параметра при создании объекта, он инициализируется при первом обращении или при чтении первой записи из файла.
Изменено в версии 2.6.
13.1.4. Объекты Writer¶Writer Objects
Объекты Writer (экземпляры DictWriter и объекты, возвращаемые функцией writer()) имеют следующие открытые методы. Для объектов row должен быть последовательностью строк или чисел для объектов Writer и словарём, отображающим имена полей в строки или числа (с предварительным преобразованием через str()) для объектов DictWriter. Обратите внимание, что комплексные числа записываются в круглых скобках. Это может вызвать некоторые проблемы у других программ, читающих CSV-файлы (если они вообще поддерживают комплексные числа).
-
csvwriter.writerow(row)¶ Записывает параметр row в файловый объект writer, отформатировав в соответствии с текущим диалектом.
-
csvwriter.writerows(rows)¶ Записывает все элементы из rows (итерацию объектов row, как описано выше) в файловый объекта средства записи, форматируя в соответствии с текущим диалектом.
Объекты Writer имеют следующий открытый атрибут:
-
csvwriter.dialect¶ Описание диалекта, используемого средством записи, доступное только для чтения.
Объекты DictWriter имеют следующий открытый метод:
-
DictWriter.writeheader()¶ Записывает строку с названиями полей (как указано в конструкторе).
Новое в версии 2.7.
13.1.5. Примеры¶Examples
Простейший пример чтения CSV-файла:
import csv
with open('some.csv', 'rb') as f:
reader = csv.reader(f)
for row in reader:
print row
Чтение файла в альтернативном формате:
import csv
with open('passwd', 'rb') as f:
reader = csv.reader(f, delimiter=':', quoting=csv.QUOTE_NONE)
for row in reader:
print row
Соответствующий простейший пример записи:
import csv
with open('some.csv', 'wb') as f:
writer = csv.writer(f)
writer.writerows(someiterable)
Регистрация нового диалекта:
import csv
csv.register_dialect('unixpwd', delimiter=':', quoting=csv.QUOTE_NONE)
with open('passwd', 'rb') as f:
reader = csv.reader(f, 'unixpwd')
Чуть более продвинутое использование reader – перехват и сообщение об ошибках:
import csv, sys
filename = 'some.csv'
with open(filename, 'rb') as f:
reader = csv.reader(f)
try:
for row in reader:
print row
except csv.Error as e:
sys.exit('file %s, line %d: %s' % (filename, reader.line_num, e))
И хотя модуль напрямую не поддерживает разбор строк, это можно легко сделать:
import csv
for row in csv.reader(['one,two,three']):
print row
Модуль csv напрямую не поддерживает чтение и запись Unicode, но он 8-битно-чист, за исключением некоторых проблем с символами ASCII NUL. Поэтому можно написать функции или классы, которые будут обрабатывать кодирование и декодирование, если избегать кодировок, использующих NUL, таких как UTF-16. Рекомендуется UTF-8.
unicode_csv_reader() ниже – это генератор, который обёртывает csv.reader для обработки данных Unicode CSV (списка строк Unicode). utf_8_encoder() – это генератор, который кодирует строки Unicode в UTF-8 по одной строке (или строке таблицы) за раз. Закодированные строки разбираются CSV-читателем, а unicode_csv_reader() декодирует ячейки, закодированные в UTF-8, обратно в Unicode:
import csv
def unicode_csv_reader(unicode_csv_data, dialect=csv.excel, **kwargs):
# csv.py не поддерживает Unicode; временно кодируйте как UTF-8:
csv_reader = csv.reader(utf_8_encoder(unicode_csv_data),
dialect=dialect, **kwargs)
for row in csv_reader:
# декодируйте UTF-8 обратно в Unicode, ячейка за ячейкой:
yield [unicode(cell, 'utf-8') for cell in row]
def utf_8_encoder(unicode_csv_data):
for line in unicode_csv_data:
yield line.encode('utf-8')
Для всех остальных кодировок можно использовать следующие классы UnicodeReader и UnicodeWriter. Они принимают дополнительный параметр encoding в своём конструкторе и обеспечивают передачу данных через реальный читатель или писатель, закодированных в UTF-8:
import csv, codecs, cStringIO
class UTF8Recoder:
"""
Итератор, который читает закодированный поток и перекодирует входные данные в UTF-8
"""
def __init__(self, f, encoding):
self.reader = codecs.getreader(encoding)(f)
def __iter__(self):
return self
def next(self):
return self.reader.next().encode("utf-8")
class UnicodeReader:
"""
CSV-ридер, который будет перебирать строки в CSV-файле "f",
который закодирован в указанной кодировке.
"""
def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
f = UTF8Recoder(f, encoding)
self.reader = csv.reader(f, dialect=dialect, **kwds)
def next(self):
row = self.reader.next()
return [unicode(s, "utf-8") for s in row]
def __iter__(self):
return self
class UnicodeWriter:
"""
Объект для записи CSV, который будет записывать строки в CSV-файл "f",
который закодирован в указанной кодировке.
"""
def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
# Перенаправить вывод в очередь
self.queue = cStringIO.StringIO()
self.writer = csv.writer(self.queue, dialect=dialect, **kwds)
self.stream = f
self.encoder = codecs.getincrementalencoder(encoding)()
def writerow(self, row):
self.writer.writerow([s.encode("utf-8") for s in row])
# Извлечь UTF-8 вывод из очереди ...
data = self.queue.getvalue()
data = data.decode("utf-8")
# ... и перекодировать его в целевую кодировку
data = self.encoder.encode(data)
# записать в целевой поток
self.stream.write(data)
# очистить очередь
self.queue.truncate(0)
def writerows(self, rows):
for row in rows:
self.writerow(row)