【问题标题】:Python 2.7 UnicodeDecodeError: 'ascii' codec can't decode bytePython 2.7 UnicodeDecodeError:“ascii”编解码器无法解码字节
【发布时间】:2012-11-22 12:07:02
【问题描述】:

我一直在用特殊字符(捷克语字母)解析一些 docx 文件(UTF-8 编码的 XML)。当我尝试输出到标准输出时,一切都很顺利,但是我无法将数据输出到文件中,

回溯(最近一次通话最后一次):
文件“./test.py”,第 360 行,在
ofile.write(u'\t\t\t\t\t\n')
UnicodeEncodeError: 'ascii' codec can't encode character u'\xed' in position 37: ordinal not in range(128)

虽然我明确地将 word 变量转换为 unicode 类型(type(word) 返回 unicode),但我尝试使用 .encode('utf-8) 对其进行编码,但我仍然遇到此错误。

下面是现在看起来的代码示例:

for word in word_list:
    word = unicode(word)
    #...
    ofile.write(u'\t\t\t\t\t<feat att="writtenForm" val="'+word+u'"/>\n')
    #...

我还尝试了以下方法:

for word in word_list:
    word = word.encode('utf-8')
    #...
    ofile.write(u'\t\t\t\t\t<feat att="writtenForm" val="'+word+u'"/>\n')
    #...

甚至这两者的结合:

word = unicode(word)
word = word.encode('utf-8')

我有点绝望,所以我什至尝试在ofile.write() 中编码单词变量

ofile.write(u'\t\t\t\t\t<feat att="writtenForm" val="'+word.encode('utf-8')+u'"/>\n')

如果有任何关于我做错的提示,我将不胜感激。

【问题讨论】:

  • 您是否尝试过其他更适合该语言的编码?
  • 我敢打赌,如果您使用的是最新版本的 Python,就不会遇到这些问题。
  • 不幸的是,我在使用更合适的编码时遇到了同样的错误,我无法使用最新的 Python 版本,因为服务器上有 v2.7 将使用脚本
  • This answer 可能会有所帮助。

标签: python unicode


【解决方案1】:

ofile 是一个字节流,您正在向其写入字符串。因此,它尝试通过编码为字节字符串来处理您的错误。这通常只对 ASCII 字符是安全的。由于word 包含非ASCII 字符,所以失败:

>>> open('/dev/null', 'wb').write(u'ä')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe4' in position 0:
                    ordinal not in range(128)

使用io.open 打开文件,使用'wt' 之类的模式和显式编码,使ofile 成为文本流:

>>> import io
>>> io.open('/dev/null', 'wt', encoding='utf-8').write(u'ä')
1L

或者,您也可以使用具有几乎相同界面的codecs.open,或者使用encode 手动编码所有字符串。

【讨论】:

  • io 输出是否以同样的方式从输入中读取数据重要吗?
  • @rivfaader 不,一点也不。只需确保数据仅包含 unicode 对象即可。在 Python 3.3+ 中运行您的代码可能会有所帮助,因为它不会静默地让 bytes 对象通过。
  • 嗯,非常感谢,我问是因为即使我以正确的方式打开它,我也会遇到同样的错误......但是我对所有变量进行了编码并且它可以工作,再次感谢
  • 嗨@phihag 我正在使用 IOByte 将文件上传到我的服务器。对于某些文件,我得到相同的错误:`UnicodeEncodeError: 'ascii' codec can't encode character u'\xed' in position 1: ordinal not in range(128)` 我该如何解决这个问题?如何将您在此处提到的相同方法应用于 IOByte 对象?
  • @Tuelho 请提出一个新问题。不要忘记发布reproducible example。如果您愿意,您可以 [给我发邮件](mailto:phihag@phihag.de) 或在此处评论并附上新问题的链接。
【解决方案2】:

Phihag 的回答是正确的。我只是想建议使用显式编码手动将 unicode 转换为字节字符串:

ofile.write((u'\t\t\t\t\t<feat att="writtenForm" val="' +
             word + u'"/>\n').encode('utf-8'))

(也许您想知道它是如何使用基本机制而不是像io.open 这样的高级巫术和黑魔法来完成的。)

【讨论】:

  • 嗯,为什么io.open 是高级魔法,甚至是black magic?我很确定理解字节流和文本流之间的区别并不难,因为我希望每个程序员都有minimal mental model of the difference
  • 每一种足够先进的科学都与魔法无异。 (Arthur C. Clark)我的意思是您的答案通过使用 lib 解决了一个特殊情况(流式传输),您不需要了解它是如何做到这一点的(即魔术)。事实上,你在更多的情况下会遇到这种麻烦,而不仅仅是使用流,而且通常知道如何解决它总是很好的。很多地方会自动将给定的 unicode 转换为 str 并在其中出现奇怪字符时立即引发错误。
  • 在 Python 3 中,几乎没有自动转换。请注意,io.open 仅在 Python 2 中的 stdlib(而不是内置函数)中。在 Python 3 中 io.open is open
【解决方案3】:

我在写入 word 文档 (.docx) 时遇到了类似的错误。特别是欧元符号 (€)。

x = "€".encode()

哪个给出了错误:

UnicodeDecodeError:“ascii”编解码器无法解码位置 0 的字节 0xe2:序数不在范围内 (128)

我是如何解决的:

x = "€".decode()

我希望这会有所帮助!

【讨论】:

    【解决方案4】:

    我在 stackoverflow 中找到的最佳解决方案是在这篇文章中: How to fix: "UnicodeDecodeError: 'ascii' codec can't decode byte" 放入代码的开头,默认编码为utf8

    # encoding=utf8
    import sys
    reload(sys)
    sys.setdefaultencoding('utf8')
    

    【讨论】:

      猜你喜欢
      • 2013-08-20
      • 2014-10-19
      • 1970-01-01
      • 1970-01-01
      • 2014-04-09
      • 2018-08-02
      • 2013-09-23
      • 2013-06-17
      • 1970-01-01
      相关资源
      最近更新 更多