这里最可能的问题是json_obj["description"]
实际上是一个UTF-8编码的str
而不是unicode
。因此,当您尝试将write
转换为codecs
包装的文件时,Python必须将其从str
解码为unicode
,以便对其进行重新编码。这是失败的部分,因为该自动解码使用sys.getdefaultencoding()
,即'ascii'
。
例如:
>>> f = codecs.open('emoji.txt', 'w+', encoding='utf-8')
>>> e = u'\U0001f1ef'
>>> print e
>>> e
u'\U0001f1ef'
>>> f.write(e)
>>> e8 = e.encode('utf-8')
>>> e8
'\xf0\x9f\x87\xaf'
>>> f.write(e8)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xf0 in position 0: ordinal not in range(128)
这里有两个可能的解决方案。
首先,你可以明确的一切unicode
尽早进行解码。我不确定你的json_obj
是从哪里来的,但我怀疑它实际上并不是stdlib json.loads
,因为默认情况下,它总是给你unicode
键和值。所以,用stdlib函数替换JSON使用的任何东西都可能解决问题。
其次,你可以放弃一切为UTF-8 str
对象,并留在二进制模式。如果你知道你在任何地方都有UTF-8,只需要open
这个文件而不是codecs.open
,然后写入时不需要任何编码。
此外,你应该认真考虑使用io.open
,而不是codecs.open
。它具有许多优点,包括:
- 如果您传递了错误的值,则会引发异常而不是做错事。
- 通常更快。
- 与Python 3的前向兼容。
- 有多个错误修复,将永远不会被移植到
codecs
。
唯一的缺点是它不向后兼容Python 2.5。除非您对此重要,否则请勿使用codecs
。
是'json_obj [“description”]'unicode'还是'str'?如果后者,它是什么编码?另外,你能在错误发生之前打印repr(json_obj [“description”]),所以我们可以看到你实际打印的是什么? – abarnert
另外,'json_obj'从哪里来?这个名字暗示了stdlib'json'模块,但是键和值显然是'str'这一事实意味着它不是...... – abarnert