Python Unicode错误

1 投票
3 回答
509 浏览
提问于 2025-04-18 04:09

我正在用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 个回答

1

你提到的问题是关于“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,你会看到第一个输出。

1

这段程序在两台机器上接收到的输入是不一样的:

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检测到的控制台使用的编码。

0

问题在于你用字节串来处理文本数据,其实应该用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中是否可以做到这一点。

撰写回答