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

时间:2015-02-08 20:01:51

标签: python json unicode encoding utf-8

另一个人无法找到正确的魔术咒语来让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']

稍后我会print执行s作为其中的一部分并查看错误。

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

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

返回一个字符串,但

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

给出了关于ascii编解码器无法解码这样一个字节的错误。文件大小(以字节为单位)与wc -c返回的字符数相同,我没有看到任何其他看起来像非ASCII字符的内容,所以我怀疑问题完全在于这个高位ASCII “A”。

我没有在我的代码中明确调用str()

我多次经历Python Unicode HOWTO次。我明白我应该“夹心”unicode处理。我想我正在这样做,但显然我还有一些误解。

大多数情况下我很困惑,因为看起来如果我在codecs.open调用中指定'utf-8',一切都应该以UTF-8发生。我不明白ASCII编解码器是如何进入的。

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


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


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

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

print(myobj)

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

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

print("%s" % myobj)

这对我来说不对。我希望这两个打印调用是等效的。


我可以通过sys.setdefaultencoding hack

来完成这项工作
import sys
reload(sys)
sys.setdefaultencoding("UTF-8")

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

这样做的正确方法是什么?我试过了

env PYTHONIOENCODING=UTF-8 ./myscript.py

但这不起作用。 (不出所料,因为问题是默认编码,而不是io编码。)

1 个答案:

答案 0 :(得分:3)

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

print s.encode('utf-8')

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