我一直在尝试编写一个简单的脚本,该脚本可以将用户输入(源自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。它具有许多优点,包括:
  • 如果传递不正确的值,则会引发异常,而不是执行错误的操作。
  • 通常更快。
  • 与Python 3正向兼容。
  • 具有许多错误修复程序,这些错误将永远不会反向移植到codecs

  • 唯一的缺点是它不能向后兼容Python 2.5。除非对您无关紧要,否则请不要使用codecs

    07-27 13:31