'ascii'编解码器无法编码错误,使用 Python 读取 JSON 时出错



还有一个人无法找到正确的魔法咒语来让Python打印UTF-8字符。

我有一个JSON文件。JSON文件包含字符串值。其中一个字符串值包含字符"à"。我有一个Python程序,它读取JSON文件并打印其中的一些字符串。有时,当程序试图打印包含"à"的字符串时,我会得到错误

UnicodeEncodeError: 'ascii' codec can't encode character u'xe0' in position 12: ordinal not in range(128)

这很难复制。有时,一个稍微不同的程序能够打印字符串"à"。仅包含此字符串的较小JSON文件不会出现此问题。如果我开始在代码中散布encode('utf-8')decode('utf-8'),它会以不可预测的方式改变结果。我还没能创建一个显示这个问题的最小代码片段和输入。

我像这样加载JSON文件。

with codecs.open(filename, 'r', 'utf-8') as f:
    j = json.load(f)

我会像这样拔出那根冒犯的绳子。

s = j['key']

稍后,我做了一个包含sprint,并看到了错误。

我很确定原始文件是UTF-8格式的,因为在交互式命令行中

codecs.open(filename, 'r', 'utf-8').read()

返回字符串,但

codecs.open(filename, 'r', 'ascii').read()

给出了一个关于ascii编解码器无法解码某个字节的错误。以字节为单位的文件大小与wc -c返回的字符数相同,而且我看不到任何其他看起来像非ASCII字符的字符,所以我怀疑问题完全在于这个高ASCII"à"。

在我的代码中,我没有对str()进行任何显式调用。

我已经学习过多次Python Unicode HOWTO。我知道我应该"三明治"处理unicode。我想我在这么做,但显然我还是有误解。

大多数情况下,我感到困惑,因为如果我在codecs.open调用中指定"utf-8",那么一切都应该以utf-8进行。我不明白ASCII编解码器是如何潜入的。

我做错了什么?我该如何调试它?


编辑:使用io模块代替codecs。同样的结果。


编辑:我没有最小的例子,但至少我有一个最小的repo场景。

我正在打印一个从导致问题的JSON中的字符串派生的对象。所以下面给出了一个错误。

print(myobj)

(请注意,我使用的是from __future__ import print_function,尽管这似乎没有什么区别。)

encode('utf-8')放在对象的__str__函数返回值的末尾并不能修复错误。但是,将打印行更改为该行确实如此。

print("%s" % myobj)

这在我看来是错误的。我希望这两个打印调用是等效的。


我可以通过执行sys.setdefaultencoding破解:来完成这项工作

import sys
reload(sys)
sys.setdefaultencoding("UTF-8")

但这显然是一个坏主意,可能会使Python在其他方面出现故障。

正确的方法是什么?我试过

env PYTHONIOENCODING=UTF-8 ./myscript.py

但那没用。(毫不奇怪,因为问题是默认编码,而不是io编码。)

当直接写入文件或将stdout重定向到文件或管道时,默认编码为ASCII,并且在写入Unicode字符串之前必须对其进行编码。对于打开的文件句柄,您可以设置一个编码以使其自动发生,但对于print,您必须使用encode()方法。

print s.encode('utf-8')

建议使用较新的io模块来代替codecs,因为它具有改进的实现,并且与Py3.x open()向前兼容。

最新更新