Как читать ввод Unicode и сравнивать строки Unicode в Python? - PullRequest
30 голосов
/ 25 января 2009

Я работаю в Python и хотел бы прочитать пользовательский ввод (из командной строки) в формате Unicode, то есть Unicode эквивалент raw_input?

Кроме того, я хотел бы проверить строки Unicode на равенство, и похоже, что стандарт == не работает.

Ответы [ 4 ]

54 голосов
/ 25 января 2009

raw_input() возвращает строки, закодированные средствами ОС или пользовательского интерфейса. Трудность в том, чтобы знать, что это за декодирование. Вы можете попробовать следующее:

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

, который должен работать правильно в большинстве случаев.

Нам нужны дополнительные данные о неработающих сравнениях Unicode, чтобы помочь вам. Однако это может быть вопросом нормализации. Учтите следующее:

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

a1 и a2 эквивалентны, но не равны:

>>> 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

Если вы дадите нам больше информации, мы, возможно, сможем вам помочь больше.

16 голосов
/ 25 января 2009

должно работать. 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
日本語 Ελληνικά

Что касается сравнения строк в юникоде: можете ли вы опубликовать пример, где сравнение не работает?

4 голосов
/ 25 января 2009

Я не совсем уверен, какой формат вы подразумеваете под "форматом Unicode", их несколько. UTF-8? UTF-16? В любом случае вы должны иметь возможность прочитать обычную строку с помощью raw_input, а затем декодировать ее, используя метод strings decode:

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

Если у вас другая входная кодировка, просто используйте «utf-16» или что-то еще вместо «utf-8». Также см. документы по кодекам для различных видов кодирования.

Сравнение тогда должно нормально работать с ==. Если у вас есть строковые литералы, содержащие специальные символы, вы должны поставить перед ними префикс «u», чтобы пометить их как юникод:

if decoded == u"äöü":
  print "Do you speak German?"

И если вы хотите снова вывести эти строки, вы, вероятно, захотите снова закодировать их в нужной кодировке:

print decoded.encode("utf-8")
1 голос
/ 25 января 2009

В общем случае, вероятно, невозможно сравнить строки в юникоде. Проблема в том, что есть несколько способов составить одни и те же символы. Простой пример - римские символы с акцентом. Хотя существуют в основном кодовые точки для всех обычно используемых акцентированных символов, также правильно составлять их из безударных базовых букв и без пробела. Эта проблема является более значимой во многих не-римских алфавитах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...