Django shell 编码错误(仅限 Debian,Ubuntu 正常)

2 投票
1 回答
1321 浏览
提问于 2025-04-17 02:22

大家好

有没有人能解释一下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 个回答

3

如果你运行下面这个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。

值得注意的是,最好检查一下在每种情况下机器的默认编码是什么。

如果有人能补充这个答案,请随时添加。

撰写回答