Python DictWriter: Запись UTF-8 закодированных CSV файлов
У меня есть список словарей, содержащих строки в формате Unicode. Модуль csv.DictWriter
может записывать список словарей в CSV-файл. Я хочу, чтобы CSV-файл был закодирован в UTF-8. Однако модуль csv
не может обрабатывать преобразование строк в формате Unicode в UTF-8.
В документации модуля csv
есть пример для преобразования всего в UTF-8:
def utf_8_encoder(unicode_csv_data):
for line in unicode_csv_data:
yield line.encode('utf-8')
Также в документации упоминается класс UnicodeWriter
.
Но как мне заставить DictWriter
работать с этими решениями? Разве они не должны внедрять себя в процесс записи, чтобы перехватывать разобранные словари и кодировать их перед записью в файл? Я не понимаю, как это сделать.
3 ответ(ов)
Вы можете конвертировать значения в UTF-8 "на лету", передавая словарь в DictWriter.writerow()
. Например:
import csv
rows = [
{'name': u'Anton\xedn Dvo\u0159\xe1k', 'country': u'\u010cesko'},
{'name': u'Bj\xf6rk Gu\xf0mundsd\xf3ttir', 'country': u'\xcdsland'},
{'name': u'S\xf8ren Kierkeg\xe5rd', 'country': u'Danmark'}
]
# реализуйте этот обертку для версий 2.6 и ниже, если нужно вывести заголовок
class DictWriterEx(csv.DictWriter):
def writeheader(self):
header = dict(zip(self.fieldnames, self.fieldnames))
self.writerow(header)
out = open('foo.csv', 'wb')
writer = DictWriterEx(out, fieldnames=['name', 'country'])
# DictWriter.writeheader() была добавлена в 2.7 (используйте класс выше для <= 2.6)
writer.writeheader()
for row in rows:
writer.writerow(dict((k, v.encode('utf-8')) for k, v in row.iteritems()))
out.close()
Вывод foo.csv будет следующим:
name,country
Antonín Dvořák,Česko
Björk Guðmundsdóttir,Ísland
Søren Kierkegård,Danmark
Если у вас возникнут дополнительные вопросы или вам потребуется помощь с другим кодом, задавайте!
Вы можете использовать прокси-класс для кодирования значений словаря по мере необходимости, например так:
# -*- coding: utf-8 -*-
import csv
d = {'a': 123, 'b': 456, 'c': u'Non-ASCII: проверка'}
class DictUnicodeProxy(object):
def __init__(self, d):
self.d = d
def __iter__(self):
return self.d.__iter__()
def get(self, item, default=None):
i = self.d.get(item, default)
if isinstance(i, unicode):
return i.encode('utf-8')
return i
with open('some.csv', 'wb') as f:
writer = csv.DictWriter(f, ['a', 'b', 'c'])
writer.writerow(DictUnicodeProxy(d))
В этом примере класс DictUnicodeProxy
инкапсулирует оригинальный словарь и переопределяет метод get
, чтобы кодировать строковые значения в формате UTF-8, если они являются объектами типа unicode
. Затем вы можете использовать этот прокси-класс при записи в CSV файл.
Когда вы вызываете csv.writer
с вашим контентом, идея заключается в том, чтобы пропустить содержимое через utf_8_encoder
, так как это обеспечит вам (utf-8) закодированный контент.
Ошибка UnicodeDecodeError при чтении CSV-файла в Pandas
UnicodeEncodeError: 'ascii' кодек не может закодировать символ u'\xa0' на позиции 20: номер не в диапазоне (128)
Как лучше всего удалить акценты (нормализовать) в строке Unicode Python?
Импорт нескольких CSV-файлов в pandas и объединение в один DataFrame
CSV-файл, созданный с помощью Python, содержит пустые строки между каждой записью