Python CSV DictReader с данными UTF-8 - PullRequest
       20

Python CSV DictReader с данными UTF-8

28 голосов
/ 15 февраля 2011

AFAIK, модуль Python (v2.6) csv по умолчанию не может обрабатывать данные Unicode, верно?В документации по Python есть пример о том, как читать из файла в кодировке UTF-8.Но этот пример возвращает только строки CSV в виде списка.Я хотел бы получить доступ к столбцам строк по имени, как это делает csv.DictReader, но с помощью входного файла CSV в кодировке UTF-8.

Может кто-нибудь сказать мне, как это сделать эффективно?Мне придется обрабатывать CSV-файлы размером в 100 МБ.

Ответы [ 7 ]

50 голосов
/ 15 февраля 2011

Я сам придумал ответ:

def UnicodeDictReader(utf8_data, **kwargs):
    csv_reader = csv.DictReader(utf8_data, **kwargs)
    for row in csv_reader:
        yield {unicode(key, 'utf-8'):unicode(value, 'utf-8') for key, value in row.iteritems()}

Примечание: это было обновлено, поэтому ключи расшифровываются согласно предложению в комментариях

2 голосов
/ 10 марта 2019

Для меня ключ был не в манипулировании аргументами csv DictReader, а в самом открывателе файлов.Это помогло:

with open(filepath, mode="r", encoding="utf-8-sig") as csv_file:
    csv_reader = csv.DictReader(csv_file)

Никакого специального класса не требуется.Теперь я могу открывать файлы с или без спецификации без сбоев.

0 голосов
/ 28 мая 2019

Это просто с пакетом unicodecsv .

# pip install unicodecsv
import unicodecsv as csv

with open('your_file.csv') as csvfile:
    reader = csv.DictReader(csvfile)
    for row in reader:
        print(row)
0 голосов
/ 23 августа 2018

Ответ не имеет методов DictWriter, поэтому вот обновленный класс:

class DictUnicodeWriter(object):

    def __init__(self, f, fieldnames, dialect=csv.excel, encoding="utf-8", **kwds):
        self.fieldnames = fieldnames    # list of keys for the dict
        # Redirect output to a queue
        self.queue = cStringIO.StringIO()
        self.writer = csv.DictWriter(self.queue, fieldnames, dialect=dialect, **kwds)
        self.stream = f
        self.encoder = codecs.getincrementalencoder(encoding)()

    def writerow(self, row):
        self.writer.writerow({k: v.encode("utf-8") for k, v in row.items()})
        # Fetch UTF-8 output from the queue ...
        data = self.queue.getvalue()
        data = data.decode("utf-8")
        # ... and reencode it into the target encoding
        data = self.encoder.encode(data)
        # write to the target stream
        self.stream.write(data)
        # empty queue
        self.queue.truncate(0)

    def writerows(self, rows):
        for row in rows:
            self.writerow(row)

    def writeheader(self):
        header = dict(zip(self.fieldnames, self.fieldnames))
        self.writerow(header)
0 голосов
/ 21 июня 2018

Пакет csvw также имеет другие функциональные возможности (для CSV с расширенными метаданными для Интернета), но он определяет класс UnicodeDictReader, охватывающий его класс UnicodeReader, который в своей основе делает именно это:

class UnicodeReader(Iterator):
    """Read Unicode data from a csv file."""
    […]

    def _next_row(self):
        self.lineno += 1
        return [
            s if isinstance(s, text_type) else s.decode(self._reader_encoding)
            for s in next(self.reader)]

Это несколько раз меня зацепило, но csvw.UnicodeDictReader действительно, действительно, нужно использовать в блоке with и ломается в противном случае. Кроме этого, модуль является достаточно универсальным и совместим с py2 и py3.

0 голосов
/ 22 января 2018

Классифицированный подход к ответу @LMatter. Благодаря этому подходу вы по-прежнему получаете все преимущества DictReader, такие как получение имен полей и номеров строк, а также обработку UTF-8

import csv

class UnicodeDictReader(csv.DictReader, object):

    def next(self):
        row = super(UnicodeDictReader, self).next()
        return {unicode(key, 'utf-8'): unicode(value, 'utf-8') for key, value in row.iteritems()}
0 голосов
/ 15 февраля 2011

Прежде всего, используйте 2.6 версию документации .Это может измениться для каждого выпуска.В нем четко сказано, что он не поддерживает Unicode, но поддерживает UTF-8. Технически , это не одно и то же.Как сказано в документации:

Модуль csv напрямую не поддерживает чтение и запись в Юникоде, но он 8-разрядный, за исключением некоторых проблем с символами ASCII NUL.Таким образом, вы можете написать функции или классы, которые обрабатывают кодирование и декодирование для вас, если вы избегаете кодировок, таких как UTF-16, которые используют NUL.Рекомендуется UTF-8.

В приведенном ниже примере (из документов) показано, как создать две функции, которые правильно читают текст как UTF-8 как CSV.Вы должны знать, что csv.reader() всегда возвращает объект DictReader.

import csv

def unicode_csv_reader(unicode_csv_data, dialect=csv.excel, **kwargs):
    # csv.py doesn't do Unicode; encode temporarily as UTF-8:
    csv_reader = csv.DictReader(utf_8_encoder(unicode_csv_data),
                            dialect=dialect, **kwargs)
    for row in csv_reader:
        # decode UTF-8 back to Unicode, cell by cell:
        yield [unicode(cell, 'utf-8') for cell in row]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...