【问题标题】:Python: How to get StringIO.writelines to accept unicode string?Python:如何让 StringIO.writelines 接受 unicode 字符串?
【发布时间】:2010-12-21 12:30:52
【问题描述】:

我得到了一个

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

存储在下面“a.desc”中的字符串上,因为它包含“£”字符。它以 unicode 字符串的形式存储在底层的 Google App Engine 数据存储中,所以这很好。 cStringIO.StringIO.writelines 函数似乎试图以 ascii 格式对其进行编码:

result.writelines(['blahblah',a.desc,'blahblahblah'])

如果措辞正确,我如何指示它将编码视为 unicode?​​p>

应用引擎在 python 2.5 上运行

【问题讨论】:

    标签: python string unicode ascii stringio


    【解决方案1】:

    您可以将 StringIO 对象包装在 codecs.StreamReaderWriter 对象中以自动编码和解码 unicode。

    像这样:

    import cStringIO, codecs
    buffer = cStringIO.StringIO()
    codecinfo = codecs.lookup("utf8")
    wrapper = codecs.StreamReaderWriter(buffer, 
            codecinfo.streamreader, codecinfo.streamwriter)
    
    wrapper.writelines([u"list of", u"unicode strings"])
    

    buffer 将填充 utf-8 编码字节。

    如果我正确理解你的情况,你只需要写,你也可以这样做:

    import cStringIO, codecs
    buffer = cStringIO.StringIO()
    wrapper = codecs.getwriter("utf8")(buffer)
    

    【讨论】:

    • 另外,cStringIO.StringIO() 返回的类文件对象在with 语句中不起作用,但codecs.StreamReaderWriter() 返回的包装器可以!
    • 这听起来类似于stackoverflow.com/q/45101658/562769 - 你知道我的问题的答案吗?
    【解决方案2】:

    StringIO documentation:

    与 StringIO 模块实现的内存文件不同,[cStringIO] 提供的内存文件不能接受无法编码为纯 ASCII 字符串的 Unicode 字符串。

    如果可能,使用 StringIO 代替 cStringIO。

    【讨论】:

    • 我切换了(cStringIO 旨在提高性能)并且它没有抛出错误,但确实打印了 '£' 而不仅仅是 '£'。为什么'Â'现在出现了?
    • '£' 是 0xc2 0xa3 的 Windows-1252 解码,即 u'£' 的 UTF-8 编码。也许您的终端、应用程序或您看到的任何地方都配置为 Windows-1252 而不是 UTF-8。
    • 嗯。本质上,我正在通过 Chrome 浏览器查看 Web 服务器响应。会是这个问题吗?
    • 在 Chrome 中,您可以设置解释页面的编码--页面菜单->编码。选择“Unicode(UTF-8)”,看看是否可以解决它...
    • 不。在这方面,ISO-8859-1 的行为与 Windows-1252 相同。您可能希望在页面标题中明确设置 UTF-8 编码,以便浏览器不必猜测编码。 (当然,除非您的应用程序中的其他内容已经以非 UTF-8 编码生成输出。)
    【解决方案3】:

    您还可以在将字符串添加到 StringIO 之前将其手动编码为 utf-8

    for val in rows:
        if isinstance(val, unicode):
            val = val.encode('utf-8')
    result.writelines(rows)
    

    【讨论】:

    • 使用isinstance 而不是type is X
    【解决方案4】:

    Python 2.6 引入了io 模块,您应该考虑使用io.StringIO(),“Unicode 文本的内存流”。

    在较旧的 python 版本中,这未优化(纯 Python),在更高版本中,已针对(快速)C 代码进行了优化。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-22
      相关资源
      最近更新 更多