Python Unicode错误
我正在用RPython和PyPy制作一个虚拟机。问题是,当我尝试添加对unicode的支持时,遇到了一个奇怪的问题。我会用字母“á”来举例。
# The char in the example is á
print len(char)
OUTPUT:
2
我知道字母“á”占用两个字节,所以它的长度是2。但问题是,当我使用下面这个例子时,我遇到了麻烦。
# In this example instr = "á" (including the quotes)
for char in instr:
print hex(int(ord(char)))
OUTPUT:
0x22
0xc3
0xa1
0x22
你可以看到有4个数字。0x22是用来表示引号的,但引号中间只有1个字母,却有两个数字。我的问题是,我在一些机器上测试这个脚本时,得到了这样的输出:
OUTPUT:
0x22
0xe1
0x22
有没有办法让两个机器上的输出结果一样?每台机器上的脚本都是完全相同的。
3 个回答
你提到的问题是关于“Python-3.x”的标签——是不是有些机器在用Python 2.x,而其他机器在用Python 3.x呢?
字符 á
实际上是 U+00E1
,所以在Python 3.x的系统上,我预计你会看到第二个输出。因为在Python 3中,字符串默认是Unicode格式,所以 len(char)
的结果会是3(包括引号在内)。
而在Python 2.x中,同样的字符在字符串中会占用两个字节,具体表现为UTF-8格式的 \xc3\xa1
(这取决于你的输入方式)。在这种情况下, len(char)
的结果会是4,你会看到第一个输出。
这段程序在两台机器上接收到的输入是不一样的:
In [154]: '\xe1'.decode('cp1252').encode('utf_8') == '\xc3\xa1'
Out[154]: True
当你在控制台输入 á
时,你可能看到的是字符 á
,但实际上控制台会把这个字符转换成一串字节。这个转换成的字节取决于控制台使用的编码方式。在Windows机器上,可能使用的是 cp1252
编码,而在Unix机器上,通常是 utf-8
编码。
所以你可能会觉得输入是一样的,但实际上控制台(也就是程序)接收到的输入是不同的。
如果你的程序能够用正确的编码来解码这些字节,然后再用unicode来处理,那么在这一点之后,两台机器上的程序就会表现得一样。如果你是通过 sys.stdin
接收字节,那么 sys.stdin.encoding
就是Python检测到的控制台使用的编码。
问题在于你用字节串来处理文本数据,其实应该用Unicode。
这意味着你需要知道输入数据的字符编码——没有所谓的纯文本。
如果你知道字符编码,那么把字节串转换成Unicode就很简单,比如:
unicode_text = bytestring.decode(encoding)
这样应该能解决你最初的问题。
还有一些Unicode标准化形式,比如:
import unicodedata
norm_text = unicodedata.normalize('NFC', unicode_text)
如果我不在程序中改变编码,那我怎么输出Unicode字符呢?
你可能是说你有一串字节,比如'\xc3\xa1'
(两个字节),可以用某种字符编码解释为文本,比如在utf-8中,它是U+00E1的Unicode编码。在不同的字符编码下,它可能会有不同的解释。请阅读我上面提供的链接每个软件开发者绝对必须了解的Unicode和字符集的基本知识(没有借口!)。
除非你的终端恰好使用和输入文件相同的字符编码,否则你需要能够在不同的字符编码之间转换。否则输出可能会出现乱码,比如你可能看到的不是á
,而是├б
。
在普通的Python中,你可以使用bytes.decode和unicode.encode方法(或者直接使用codecs
模块)。我不知道在RPython中是否可以做到这一点。