Как мне решить проблемы с декодированием и печатью греческих символов с использованием Python?

1

Я создаю простую игру, предназначенную для запроса пользователю греческого перевода английского слова. Например:

cow: # here, the gamer would answer with *η αγελάδα* in order to score one point.

Я использую вспомогательную функцию для чтения и декодирования из txt файла. Я делаю это, используя следующий код в указанной функции:

# The variable filename refers to my helper function sole parameter, it takes the 
# above mentioned txt file as an argument.
words_text = codecs.open(filename, 'r', 'utf-8')

Эта вспомогательная функция затем считывает каждую строку. Строки напоминают следующее:

# In stack data, when I debug, it reads as u"\η αγελάδα - cow\r\n".
u"\u03b7 \u03b1\u03b3\u03b5\u03bb\u03ac\u03b4\u03b1 - cow\r\n"

В первой строке файла при чтении, однако, имеется нежелательный префикс, ueff-:

# u"\ufeffη αγελάδα - cow\r\n"
u"\ufeff\u03b7 \u03b1\u03b3\u03b5\u03bb\u03ac\u03b4\u03b1 - cow\r\n"

Примечание. После проверки ответа на ответ, я узнал, что preended oject (ueff) является подписью спецификации (используется для выделения UTF- 8 из других кодировок).

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

{u'\u03b7 \u03b1\u03b3\u03b5\u03bb\u03ac\u03b4\u03b1': 'cow'}

Затем в моей основной функции я использую следующее для хранения пользовательского ввода:

# This is the code for the prompt I noted at the beginning.
# The variable gr_en_dict is the dictionary noted right above.
for key in gr_en_dict:
    user_reply = raw_input('%s: ' % (gr_en_dict[key])).decode(sys.stdout.encoding)

Затем я сравниваю значение пользовательского ввода с соответствующим ключом в словаре:

# I imported unicodedata as ud.
if ud.normalize('NFC', user_reply) == ud.normalize('NFC', key):
        score += 1

В ответ на вопрос, похожий на мой, пользователь TΖΩΤΖΙΟΥ сказал, что он импортирует модуль unicodedata и вызывает метод нормализации (который я сделал в коде выше), но я подозреваю, что это может и не понадобиться. К сожалению, этот шаг программы не вызывает беспокойства, поскольку у меня есть проблема, декодирующая ввод пользователя. Чтобы продемонстрировать, когда я печатаю каноническое строковое представление user_reply и соответствующего ключа в моем словаре [используя built- in repr()], я получаю следующий результат:

пользовательский ввод (user_reply):

u'? \u03b1?\u03b5??\u03b4\u03b1'

Если я печатаю пользовательский ввод без функции repr(), он выглядит так:

? α?ε??δα

в моем словаре:

u'\u03b7 \u03b1\u03b3\u03b5\u03bb\u03ac\u03b4\u03b1'

Если я печатаю его без repr(), я получаю сообщение об ошибке:

UnicodeEncodeError: 'charmap' codec can't encode character u'\u03b7' in position 0: character maps to <undefined>

Обратите внимание на вопросительные знаки в пользовательском вводе и на ошибку, возникающую при попытке напечатать собственно греческое слово. Это, кажется, суть моей проблемы.

Итак, что именно мне нужно сделать, чтобы декодировать пользовательский ввод и правильно отобразить все греческие символы?

При использовании моей собственной кодовой страницы:

C:\>chcp
Active code page: 437

C:\>\python25\python
Python 2.5.4 (r254:67916, Dec 23 2008, 15:10:54) [MSC v.1310 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.stdout.encoding
'cp437'
>>> print '? α?ε??δα'
? α?ε??δα
>>>

При использовании греческой кодовой страницы: (как ни странно, она отображается правильно, только когда я сначала скопирую ее в буфер обмена, а затем вставьте ее в приложение типа слова. Я бы разместил изображение того, что он на самом деле печатает в консоли по умолчанию, но Мне не хватает репутации, чтобы сделать это.)

C:\>chcp 869
Active code page: 869

C:\>\python25\python
Python 2.5.4 (r254:67916, Dec 23 2008, 15:10:54) [MSC v.1310 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.stdout.encoding
'cp869'
>>> print ' η αγελάδα'
 η αγελάδα
>>> print 'η αγελάδα'
η αγελάδα
>>>

ВВЕРХ: Мне пришлось менять шрифт консоли по умолчанию на Lucida Console. Это решило мое несоответствие.

  • 0
    Какая кодировка печатается с помощью sys.stdin.encoding и sys.stdout.encoding ? Если вы можете ввести греческую строку в командной строке, она должна быть декодируемой в Unicode и кодируемой для печати.
Теги:
printing
unicode
raw-input

2 ответа

3
Лучший ответ

Для части вашего вопроса используйте:

words_text = codecs.open(filename, 'r', 'utf-8-sig')

и он обработает обработку byte- order- метки \ufeff.

Технически это:

user_reply = raw_input('%s: ' % (gr_en_dict[key])).decode(sys.stdout.encoding)

должен быть:

user_reply = raw_input('%s: ' % (gr_en_dict[key])).decode(sys.stdin.encoding)

но на практике они должны быть одинаковыми.

Я считаю, что проблема в кодировке в консоли по умолчанию не поддерживает всех греческих символов. Когда я перехожу на греческую кодовую страницу, все начинает работать лучше. Обратите внимание, что я могу вставить правильные символы в инструкцию print ниже, но cp437 фактически не поддерживает все символы, поэтому при печати неподдерживаемые символы заменяются вопросительным знаком:

C:\>chcp
Active code page: 437

C:\>python
Python 2.7.1 (r271:86832, Nov 27 2010, 18:30:46) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.stdout.encoding
'cp437'
>>> print 'η αγελάδα - cow'
? α?ε??δα - cow

Если я переключусь на греческую кодовую страницу (869 или 1253), она работает:

C:\>chcp 869
Active code page: 869

C:\>python
Python 2.7.1 (r271:86832, Nov 27 2010, 18:30:46) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.stdout.encoding
'cp869'
>>> print 'η αγελάδα - cow'
η αγελάδα - cow
>>>
  • 0
    Я переключил кодовую страницу и попытался сделать то, что вы описали в нижней половине вашего ответа; тем не менее, моя попытка в конечном итоге напечатала случайные греческие символы, а не η αγελάδα .
  • 0
    Какая у вас родная кодовая страница, прежде чем что-то менять? Кроме того, какая версия Python? Покажите полный рабочий пример, демонстрирующий проблему.
1

Стандартная оболочка Windows имеет проблемы с расширенными символами. Я бы предложил использовать что-то вроде Windows PowerShell.

Для символа '\ ufeff', который является знаком порядка байтов, вы можете выполнить следующую проверку после чтения в файле:

words_text = codecs.open(filename, 'r', 'utf-8')
words_text_lines = words_text.readlines()

if words_text_lines and words_text_lines[0][0]==unicode(codecs.BOM_UTF8, 'utf8'):
    words_text_lines[0] = words_text_lines[0][1:]

Таким образом вы отбрасываете его, если он там.

  • 0
    На самом деле, для метки порядка байтов решение Марка Толонена делает то же самое, что и мое, но намного чище.
  • 0
    У ОП уже есть написанная программа на Python, и вопрос помечен как Python. Предложение Win PowerShell не поможет.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню