2009-05-27 91 views
7

有人能向我解释这个奇怪的事情:Python中的Unicode

当在Python Shell我键入下面的西里尔字符串:

>>> print 'абвгд' 
абвгд 

但是当我键入:

>>> print u'абвгд' 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-9: ordinal not in range(128) 

由于第一个tring出来正确,我认为我的OS X终端可以代表unicode,但事实证明它不能在第二种情况下。为什么?

回答

16
>>> print 'абвгд' 
абвгд 

当您键入某些字符时,您的终端将决定如何将这些字符表示给应用程序。您的终端可能会将字符提供给编码为utf-8,ISO-8859-5的应用程序或甚至只有您的终端才能理解的内容。 Python将这些字符视为一些字节序列。然后python将这些字节按原样打印出来,并且终端以某种方式解释它们以显示字符。由于终端通常解释相同的方式字节之前编码它们,就像您键入它显示的一切。

>>> u'абвгд' 

在这里,你在某些字符,在Python解释器作为一个字节的顺序到达类型,可能由终端以某种方式进行编码。与u前缀python尝试将此数据转换为unicode。为了正确地做到这一点,python必须知道你的终端使用什么编码。在你的情况下,它看起来像Python猜测你的终端编码是ASCII,但接收到的数据不匹配,所以你得到一个编码错误。

的直接的方式在交互式会话创建unicode字符串因此将是这样的:

>>> us = 'абвгд'.decode('my-terminal-encoding') 

在文件列表中,你也可以用一个特殊的模式行指定文件的编码:

# -*- encoding: ISO-8859-5 -*- 
us = u'абвгд' 

有关设置默认输入编码的其他方法,您可以查看sys.setdefaultencoding(...)sys.stdin.encoding

0

unicode对象在可以显示在某些控制台之前需要进行编码。尝试

u'абвгд'.encode() 

而不是编码统一为一个字符串对象(最有可能使用UTF-8作为默认编码,而是取决于你的Python配置)还

+0

这是行不通的 - 编码()抛出了同样的错误。 – disc0dancer 2009-05-27 22:35:10

3

,确保终端编码设置为Unicode/UTF-8(而不是ASCII,这似乎是你的设置):

http://www.rift.dk/news.php?item.7.6

+0

我想到了这一点,但是我错误的是我的终端如果输入正常的字符串,就会显示unicode - 例如, 'уникоде',但是如果我尝试打印与u'уникоде' – disc0dancer 2009-05-27 22:36:29

9

除了确保您的OS X终端设置为UTF-8,您可能希望设置你的Python SYS的默认编码UTF-8或更好。在/Library/Python/2.5/site-packages中创建一个名为sitecustomize.py的文件。在这个文件中提出:

import sys 
sys.setdefaultencoding('utf-8') 

setdefaultencoding方法仅由网站模块,并从sys namespace once startup has completed删除。因此,您需要启动新的python解释器才能使更改生效。您可以在sys.getdefaultencoding()启动后随时验证当前的默认编码。

如果人物不是已经Unicode和你需要将它们转换,使用decode方法上的绳子,以便从其他一些字符集文本解码成Unicode ......最好到指定字符集:

s = 'абвгд'.decode('some_cyrillic_charset') # makes the string unicode 
print s.encode('utf-8') # transform the unicode into utf-8, then print it 
+0

相同的字符串时会抛出错误。这解决了我的问题,虽然repr()解释不正确。我在我的问题上犯了一个错误(对不起),现在我修正了 - 我实际上打印了u'абвгд'字符串,所以它不是repr()错误。 事实上 - 如果我省略了打印语句,我不会收到错误信息 - 我只是得到了我的猜测将会是'xd0 \ xb0 \ xd0 \ xb1 \ xd0 \ xb2 \ xd0 \ xb3 \ xd0 \ xb4' 默认编码mac-roman可以代表cyrilic chars(另一个没有意义......),但在unicode中不是cyrilic。我真的没有得到这个:) – disc0dancer 2009-05-27 23:18:44

+0

感谢信息discodancer ...你是对的...我的坏。 – 2009-05-27 23:20:22

+0

请勿更改系统默认编码;修改你的Unicode值。更改默认编码可以破坏依赖于*默认行为*的库。有一个原因,你必须强制一个模块重新加载,然后才能做到这一点。 – 2014-05-15 11:37:46

0

'абвгд' 是不是一个Unicode字符串

u'абвгд”是Unicode字符串

没有编码它们不能打印unicode字符串。当你在应用程序中处理字符串时,你想要确保任何输入都被解码,并且任何输出都被编码。这样,你的应用程序将只在内部处理unicode字符串,并以UTF8格式输出字符串。

参考:

>>> 'абвгд'.decode('utf8') == u'абвгд' 
>>> True 
13

对于Python 2.6,你可以使用环境变量PYTHONIOENCODING来告诉Python,你的终端是UTF-8的能力。将其永久保留最简单的方法是通过添加以下行到您的~/.bash_profile

export PYTHONIOENCODING=utf-8 

Terminal.app showing unicode output from Python