带有 UTF-8 数据的 Python CSV DictReader
Posted
技术标签:
【中文标题】带有 UTF-8 数据的 Python CSV DictReader【英文标题】:Python CSV DictReader with UTF-8 data 【发布时间】:2011-06-27 15:25:12 【问题描述】:AFAIK,默认情况下 Python (v2.6) csv 模块无法处理 unicode 数据,对吗?在 Python 文档中有一个 example 说明如何从 UTF-8 编码文件中读取。但此示例仅将 CSV 行作为列表返回。
我想按名称访问行列,因为它由 csv.DictReader
完成,但使用 UTF-8 编码的 CSV 输入文件。
谁能告诉我如何以有效的方式做到这一点?我将不得不处理 100 兆字节大小的 CSV 文件。
【问题讨论】:
【参考方案1】:我自己想出了一个答案:
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()
注意:这已更新,因此密钥会根据 cmets 中的建议进行解码
【讨论】:
然后选择它作为答案:) 好的,不知道我能做到这一点:) 我会等一段时间看看是否有人知道更好的方法,然后接受它。 -1 这不会解码文件第一行中的字典键。 无需为回答您自己的问题而道歉。这是 *** 的预期用途之一。现在其他人都可以分享您自学的内容! 正如 John Machin 提到的,这不会解码密钥; yield 行应该是: yield unicode(key, 'utf-8'):unicode(value, 'utf-8') for key, value in row.iteritems()【参考方案2】:对我来说,关键不在于操纵 csv DictReader args,而在于文件打开器本身。这成功了:
with open(filepath, mode="r", encoding="utf-8-sig") as csv_file:
csv_reader = csv.DictReader(csv_file)
不需要特殊课程。现在我可以打开带有或不带有 BOM 的文件而不会崩溃。
【讨论】:
TypeError: 'encoding' is an invalid keyword argument for this function @ATX Odd - 我想知道你是在 python2 上而不是 3 上吗? 是的,确实是 p2【参考方案3】:首先,使用2.6 version of the documentation。每个版本都可以更改。它明确表示它不支持 Unicode,但确实支持 UTF-8。 Technically,这些不是一回事。正如文档所说:
csv 模块不直接支持读写 Unicode,但它是 8-bit-clean 保存 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]
【讨论】:
csv.reader()
在我测试时不返回 DictReader 对象。您确定吗?此外,您的示例中的 yield 语句仅返回一个包含值的列表,而不是一个字典。
我猜你对 DictReader 的看法是正确的。我将示例更改为调用csv.DictReader
而不是csv.reader
。请注意,除了这个差异之外,这直接在文档之外。
我认为你的读者仍然没有返回一个字典,而只是一个行值列表(参见 yield 语句)。但是感谢您的回答,无论如何,在重新阅读您提到的文档后,我自己想出了一个解决方案(最后:))
@LMatter 你介意分享你找到的解决方案吗?【参考方案4】:
@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()
【讨论】:
【参考方案5】:csvw
package 还具有其他功能(用于 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 兼容。
【讨论】:
【参考方案6】:答案没有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)
【讨论】:
【参考方案7】:使用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)
【讨论】:
以上是关于带有 UTF-8 数据的 Python CSV DictReader的主要内容,如果未能解决你的问题,请参考以下文章
无法将带有塞浦路斯数据的csv文件上传到Google数据工作室-编码utf-8错误