繁体   English   中英

带有UTF-8数据的Python CSV DictReader

[英]Python CSV DictReader with UTF-8 data

AFAIK,Python(v2.6)csv模块默认不能处理unicode数据,对吗? 在Python文档中有一个关于如何从UTF-8编码文件中读取的示例 但是此示例仅将CSV行作为列表返回。 我想按名称访问行列,因为它是由csv.DictReader完成的,但是使用UTF-8编码的CSV输入文件。

谁能告诉我如何以有效的方式做到这一点? 我将不得不处理100个MByte大小的CSV文件。

我自己想出了一个答案:

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()}

注意:这已更新,因此根据评论中的建议解码密钥

对我来说,关键不是操纵csv DictReader args,而是文件开启器本身。 这样就可以了:

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

不需要特殊课程。 现在我可以使用或不使用BOM打开文件而不会崩溃。

基于分类的@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()}

首先,使用2.6版本的文档 它可以针对每个版本进行更改。 它清楚地表明它不支持Unicode,但它确实支持UTF-8。 从技术上讲 ,这些并不是一回事。 正如文档所说:

csv模块不直接支持读取和写入Unicode,但除了ASCII NUL字符的一些问题外,它还是8位清除。 因此,只要您避免使用像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]

csvw也有其他功能(对于Web的元数据丰富的CSV),但是它定义了一个围绕其UnicodeReader类的UnicodeDictReader类,其核心就是这样:

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。

答案没有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)

使用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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM