我一直在尝试编写一个简单的脚本,该脚本可以将用户输入(源自iPhone)保存到文本文件中。我遇到的问题是,当用户使用表情符号图标时,它会破坏整个内容。
操作系统:Ubuntu
Python版本:2.7.3
我的代码目前看起来像这样
f = codecs.open(path, "w+", encoding="utf8")
f.write("Desc: " + json_obj["description"])
f.close()
在描述变量中传递表情符号字符时,出现错误:
UnicodeEncodeError:“ascii”编解码器无法对位置7-8中的字符进行编码:序数不在范围内(128)
任何可能的帮助表示赞赏。
最佳答案
这里最可能出现的问题是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
。它具有许多优点,包括:codecs
。 唯一的缺点是它不能向后兼容Python 2.5。除非对您无关紧要,否则请不要使用
codecs
。