【问题标题】:unicodecsv.DictReader not working with io.StringIO (Python 2.7)unicodecsv.DictReader 不适用于 io.StringIO (Python 2.7)
【发布时间】:2015-03-22 13:17:28
【问题描述】:

我试图使用 csv.DictReader 来解析带有特殊字符的 UTF-8 数据,但出现以下错误:

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

我在网上阅读并发现 Python 2.7 的 csv 库不处理 Unicode。我找了一个替代库,发现unicodecsv

我用 unicodecsv 替换了 csv,但我得到了同样的错误。这是我的代码的简化版本:

from io import StringIO
from unicodecsv import DictReader, Dialect, QUOTE_MINIMAL

data = (
    'first_name,last_name,email\r'
    'Elmer,Fudd,elmer@looneytunes.com\r'
    'Jo\xc3\xa3o Ant\xc3\xb4nio,Ara\xc3\xbajo,joaoantonio@araujo.com\r'
)

unicode_data = StringIO(unicode(data, 'utf-8-sig'), newline=None)

class CustomDialect(Dialect):
    delimiter = ','
    doublequote = True
    escapechar = '\\'
    lineterminator = '\r\n'
    quotechar = '"'
    quoting = QUOTE_MINIMAL
    skipinitialspace = True

rows = DictReader(unicode_data, dialect=CustomDialect)

for row in rows:
    print row

如果我用 BytesIO 替换 StringIO,编码有效,但我无法再发送 newlines 参数,然后我得到:

Error: new-line character seen in unquoted field - do you need to open the file in universal-newline mode?

有人知道我该如何解决这个问题吗? unicodecsv 不应该处理 StringIO 吗?谢谢

【问题讨论】:

    标签: python-2.7 csv utf-8 stringio


    【解决方案1】:

    我在 unicodecsv github 页面中打开了an issue,结果发现(与 imo 有点违反直觉)unicodecsv 阅读器需要一个字节串,而不是一个 unicode 对象。

    在我花了一些时间让 Unicode 和编码的整个事情在我的脑海中变得更清晰之后,事实证明我一开始并不真的需要 unicodecsv。毕竟,最初的问题是io.StringIO 在使用.next() 进行迭代时,将 unicode 对象返回给 csv.DictReader,它需要字节串。因此,如果 unicodecsv 也需要字节串,它显然无法解决问题。

    我的解决方案是更改我传递给 csv.DictReader 的类文件对象,以便它返回正确编码的字节字符串而不是 unicode 对象:

    class UTF8EncodedStringIO(StringIO):
        def next(self):
            return super(UTF8EncodedStringIO, self).next().encode('utf-8')
    
    udata = UTF8EncodedStringIO(unicode(data, 'utf-8-sig'), newline=None)
    

    通过围绕 StringIO 而不是使用 BytesIO 编写这个简单的包装器,我可以解决编码问题并从 newline 参数中获益。有一些解码/编码开销,但我没有其他选择。如果有人有更好的建议,请随时分享。

    【讨论】:

      猜你喜欢
      • 2012-01-13
      • 2017-02-22
      • 2016-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多