【问题标题】:how to write a unicode csv in Python 2.7如何在 Python 2.7 中编写 unicode csv
【发布时间】:2014-05-09 03:26:22
【问题描述】:

我想将数据写入文件,其中 CSV 中的一行应如下所示(直接来自 Python 控制台):

row = ['\xef\xbb\xbft_11651497', 'http://kozbeszerzes.ceu.hu/entity/t/11651497.xml', "Szabolcs Mag '98 Kft.", 'ny\xc3\xadregyh\xc3\xa1za', 'ny\xc3\xadregyh\xc3\xa1za', '4400', 't\xc3\xbcnde utca 20.', 47.935175, 21.744975, u'Ny\xedregyh\xe1za', u'Borb\xe1nya', u'Szabolcs-Szatm\xe1r-Bereg', u'Ny\xedregyh\xe1zai', u'20', u'T\xfcnde utca', u'Magyarorsz\xe1g', u'4405']

Py2k 不做 Unicode,但我有一个 UnicodeWriter 包装器:

import cStringIO, codecs
class UnicodeWriter:
    """
    A CSV writer which will write rows to CSV file "f",
    which is encoded in the given encoding.
    """

    def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
        # Redirect output to a queue
        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([unicode(s).encode("utf-8") for s in row])
        # 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)

但是,这些行仍然会产生以下可怕的编码错误消息:

f.write(codecs.BOM_UTF8)
writer = UnicodeWriter(f)
writer.writerow(row)

UnicodeEncodeError: 'ascii' codec can't encode character u'\xfc' in position 9: ordinal not in range(128)

有什么可做的?谢谢!

【问题讨论】:

  • 没关系,看到csv 模块配方确实使用了这种舞蹈。
  • 也许是在传递字节字符串?如果row 包含任何属于str 的数据,其中字符在0x80 到0xFF 范围内,那么您会得到确切的异常。
  • 我无法重现您的异常使用提供的示例行,当然。这被正确写入文件为'\xef\xbb\xbft_23434419,http://kozbeszerzes.ceu.hu/entity/t/23434419.xml,FOREX MEDICAL Kft.,budapest,budapest,1221,kossuth lajos utca 21.,47.4270908,19.0383069,Budapest,XXII. ker\xc3\xbclet,Budapest,Budapest,21,Kossuth Lajos utca,Magyarorsz\xc3\xa1g,1221\r\n'
  • 安装 unicodecsv 并使用它来读取您的 CSV(以及编写新的);它会为你处理解码。它使用与编写时相同的包装器。
  • 您没有将地址编码为 UTF-8,对吧。 {'address': address.encode('utf8'), ....

标签: python python-2.7 csv unicode


【解决方案1】:

您正在传递包含非 ASCII 数据的字节串,并且正在使用此行的默认编解码器将这些字节串解码为 Unicode:

self.writer.writerow([unicode(s).encode("utf-8") for s in row])

unicode(bytestring) 无法解码为 ASCII 的数据失败:

>>> unicode('\xef\xbb\xbft_11651497')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xef in position 0: ordinal not in range(128)

在将数据传递给写入器之前将数据解码为 Unicode:

row = [v.decode('utf8') if isinstance(v, str) else v for v in row]

这假定您的字节字符串值包含 UTF-8 数据。如果您有多种编码,请尝试在源点解码为 Unicode;您的程序首先获取数据的位置。不管数据来自哪里,或者它是否已经被编码为 UTF-8,无论如何,您确实想这样做。

【讨论】:

    猜你喜欢
    • 2013-08-30
    • 2015-01-22
    • 2016-12-15
    • 2013-02-06
    • 1970-01-01
    • 1970-01-01
    • 2017-06-07
    • 1970-01-01
    • 2016-07-29
    相关资源
    最近更新 更多