7

我一直在尝试编写一个简单的脚本,可以将用户输入(来自 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)

任何可能的帮助表示赞赏。

4

1 回答 1

5

这里最可能的问题是它json_obj["description"]实际上是 UTF-8 编码的str,而不是unicode. 因此,当您尝试将write其转换为codecs-wrapped 文件时,Python 必须将其从strto解码,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键和值。因此,将您用于 JSON 的任何内容替换为 stdlib 函数可能会解决问题。

其次,您可以将所有内容保留为 UTF-8str对象并保持二进制模式。如果您知道到处都有 UTF-8,只需open使用文件而不是codecs.open, 并且无需任何编码即可写入。


此外,您应该强烈考虑使用io.open而不是codecs.open. 它有许多优点,包括:

  • 如果您传递不正确的值,则引发异常而不是做错事。
  • 通常更快。
  • 与 Python 3 前向兼容。
  • 有许多永远不会被向后移植到codecs.

唯一的缺点是它不向后兼容 Python 2.5。除非这对您很重要,否则不要使用codecs.

于 2013-07-08T18:29:01.347 回答