如何在Python中读取Unicode输入并比较Unicode字符串?

31

我使用Python编程,并且想要以Unicode格式读取用户输入(从命令行),即raw_input的Unicode等价形式。

此外,我也想要测试Unicode字符串是否相等,但是似乎标准的==无法正常工作。

4个回答

54

raw_input() 返回由操作系统或UI工具编码的字符串。难点在于要知道使用的是哪种解码方式。您可以尝试以下方法:

import sys, locale
text= raw_input().decode(sys.stdin.encoding or locale.getpreferredencoding(True))

在大多数情况下,这应该可以正常工作。

我们需要更多关于Unicode比较不起作用的数据才能帮助您。但是,这可能与规范化有关。请考虑以下内容:

>>> a1= u'\xeatre'
>>> a2= u'e\u0302tre'

a1a2 是等价但不相等的:

>>> print a1, a2
être être
>>> print a1 == a2
False

因此,您可能希望使用unicodedata.normalize()方法:

>>> import unicodedata as ud
>>> ud.normalize('NFC', a1)
u'\xeatre'
>>> ud.normalize('NFC', a2)
u'\xeatre'
>>> ud.normalize('NFC', a1) == ud.normalize('NFC', a2)
True

如果您提供更多信息,我们可能会更好地帮助您。


4
应该是:text = raw_input().decode(sys.stdin.encoding)这样表述更加流畅,意思和原文相同。 - netom

17

这应该可以正常工作。raw_input返回一个字节字符串,你必须使用正确的编码进行解码,以获取你的unicode对象。例如,在Python 2.5 / Terminal.app / OSX下,以下代码对我有效:

>>> bytes = raw_input()
日本語 Ελληνικά
>>> bytes
'\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e \xce\x95\xce\xbb\xce\xbb\xce\xb7\xce\xbd\xce\xb9\xce\xba\xce\xac'

>>> uni = bytes.decode('utf-8') # substitute the encoding of your terminal if it's not utf-8
>>> uni
u'\u65e5\u672c\u8a9e \u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac'

>>> print uni
日本語 Ελληνικά

关于比较Unicode字符串:你能否提供一个比较不起作用的示例?


1
你会如何在Python3中完成同样的事情? - Aaron Esau

4

我不确定“Unicode格式”指的是哪种格式,因为有好几种。UTF-8?UTF-16?无论如何,您应该可以使用raw_input读取正常字符串,然后使用字符串的decode方法对其进行解码:

raw = raw_input("Please input some funny characters: ")
decoded = raw.decode("utf-8")

如果您有不同的输入编码,只需使用“utf-16”或其他编码替换“utf-8”。此外,请参阅codecs模块文档以获取不同种类的编码。
如果您有包含特殊字符的字符串文字,则应在前面加上“u”以将其标记为Unicode,并可以使用“==”进行比较。
if decoded == u"äöü":
  print "Do you speak German?"

如果你想再次输出这些字符串,你可能需要在所需的编码下重新进行编码:

print decoded.encode("utf-8")

1
通常情况下,比较Unicode字符串可能是不可行的。问题在于有几种方法可以组合相同的字符。一个简单的例子是带重音的罗马字符。虽然基本上所有常用的带重音字符都有代码点,但从未带重音的基础字母和非间距重音符号组合也是正确的。这个问题在许多非罗马字母表中更为显著。

在比较之前,可以对输入字符串进行规范化或反规范化。这就是 unicodedata 模块的作用。 - tzot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接