Django shell 编码错误(仅限 Debian,Ubuntu 正常)
大家好
有没有人能解释一下Django的manage.py shell控制台背后发生了什么?
我遇到的问题是这样的。我正在开发一个Django应用,它使用urllib来解析一些HTML页面,以获取其中的信息。这些信息是俄语的,所以它应该是unicode格式(在这个例子中是地址字符串)。接下来,我的脚本将这个地址传递给另一个第三方模块,但它出错了,因为这个字符串不是有效的unicode字符串(我试图从地址中获取地理编码)。我尝试用print address
命令将字符串(在这个例子中是解析后的地址)打印到控制台,但失败了:
File "<console>", line 1, in <module>
... some useless stacktrace ...
print address
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
现在有趣的部分来了。
我有两台电脑:一台是运行Ubuntu的工作站,Python版本是2.7.2,另一台是运行Debian Lenny的VPS,同样是Python 2.7.2。我在这两台机器上以相同的方式启动解析器:执行python manage.py shell
并从中调用我的函数。
一开始我在这两个安装上都遇到了相同的错误,但后来我注意到我的Python编码设置为'ascii'(import sys; sys.getdefaultencoding()
)。当我把
import sys; reload(sys).setdefaultencoding('utf-8')
放进settings.py后,Ubuntu上的问题解决了。现在我可以正确打印出来,比如г. Челябинск, ул. Кирова, д. 27, КТК Набережный
,但在Debian上却不行。
如果我删除这个print address
语句,那么我会得到不可读的地理位置错误,但这又只发生在Debian上。Ubuntu工作得很好:
Failed to geodecode address [г. ЧелÑбинÑк, Ñл. 1-ой ÐÑÑилеÑки, 17/1, ÑÑнок ÐÑÑак, 1-з]
无论怎么用unicode(address).encode('utf-8')
的魔法都无济于事。
所以我就是搞不懂。是什么导致这两台机器之间的差异,让我这么头疼?
1 个回答
如果你运行下面这个Python脚本,你会看到发生了什么:
# -*- coding: utf-8 -*-
a = r"Челябинск"
print "Encode from UTF-8 to UTF-8:",unicode(a,'utf-8').encode('utf-8')
print "Encode from ISO8859-1 to UTF-8:",unicode(a,'iso8859-1').encode('utf-8')
输出结果是:
从ISO8859-1编码到UTF-8: Челябинск
从ISO8859-1编码到UTF-8: ЧелÑбинÑк
简单来说,你是在处理一个已经是UTF-8编码的字符串,然后再把它当成ISO8859-1编码重新编码一次,最后再转回UTF-8。
值得注意的是,最好检查一下在每种情况下机器的默认编码是什么。
如果有人能补充这个答案,请随时添加。