2013-07-08 51 views
5

我一直在试图写一个简单的脚本,可以保存用户输入(源自iPhone)到文本文件。我遇到的问题是,当用户使用表情符号图标时,它会打破整个事情。Python写入(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)

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

+0

是'json_obj [“description”]'unicode'还是'str'?如果后者,它是什么编码?另外,你能在错误发生之前打印repr(json_obj [“description”]),所以我们可以看到你实际打印的是什么? – abarnert

+0

另外,'json_obj'从哪里来?这个名字暗示了stdlib'json'模块,但是键和值显然是'str'这一事实意味着它不是...... – abarnert

回答

3

这里最可能的问题是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