Невозможно декодировать строку Unicode в Python 2.4 - PullRequest
4 голосов
/ 20 марта 2009

Это в Python 2.4. Вот моя ситуация. Я вытаскиваю строку из базы данных, и она содержит пометку 'o' (\ xf6). В этот момент, если я запускаю type (value), он возвращает str. Затем я пытаюсь запустить .decode ('utf-8') и получаю сообщение об ошибке (кодек utf8 не может декодировать байты в позиции 1-4).

На самом деле моя цель - просто заставить тип (значение) возвращать юникод. Я нашел предыдущий вопрос у этого была некоторая полезная информация, но пример из выбранного ответа, кажется, не работает для меня. Здесь я что-то не так делаю?

Вот код для воспроизведения:

Name = 'w\xc3\xb6rner'.decode('utf-8')
file.write('Name: %s - %s\n' %(Name, type(Name)))

На самом деле я никогда не доходил до оператора write, потому что он не срабатывает при первом утверждении.

Спасибо за вашу помощь.

Edit:

Я проверил, что кодировка БД - utf8. Поэтому в моем коде для воспроизведения я изменил «\ xf6» на «\ xc3 \ xb6», и сбой все еще происходит. Есть ли разница между utf-8 и utf8?

Подсказка по использованию кодеков для записи в файл удобна (я обязательно буду ее использовать), но в этом сценарии я пишу только в файл журнала для целей отладки.

Ответы [ 4 ]

10 голосов
/ 20 марта 2009

Ваша строка не является в кодировке UTF8. Если вы хотите «декодировать» строку в Unicode, ваша строка должна быть в кодировке, указанной вами параметром. Я попробовал это, и он отлично работает:

print 'w\xf6rner'.decode('cp1250')

EDIT

Для записи в файл юникодных строк вы можете использовать модуль кодеков:

import codecs
f = codecs.open("yourfile.txt", "w", "utf8")
f.write( ... )

Удобно указать кодировку ввода / вывода и использовать строку 'unicode' во всем коде, не беспокоясь о различных кодировках.

5 голосов
/ 20 марта 2009

Это явно 1-байтовая кодировка. 'ö' в UTF-8 - это \ xc3 \ xb6.

Кодировка может быть:

  • ISO-8859-1
  • ISO-8859-2
  • ISO-8859-13
  • ISO-8859-15
  • Win-1250
  • Win-1252
3 голосов
/ 20 марта 2009

Вам необходимо использовать «ISO-8859-1»:

Name = 'w\xf6rner'.decode('iso-8859-1')
file.write('Name: %s - %s\n' %(Name, type(Name)))

utf-8 использует 2 байта для экранирования чего-либо за пределами ascii, но здесь это всего 1 байт, поэтому iso-8859-1, вероятно, является правильным.

2 голосов
/ 20 марта 2009

Таким образом, в моем коде для воспроизведения я изменил '\ xf6' на '\ xc3 \ xb6', и ошибка все еще происходит

Не в первой строке это не так:

>>> 'w\xc3\xb6rner'.decode('utf-8')
u'w\xf6rner'

Во второй строке произойдет ошибка:

>>> file.write('Name: %s - %s\n' %(Name, type(Name)))
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf6' in position 7: ordinal not in range(128)

Это вполне то, что вы ожидаете, пытаясь записать не-ASCII символы Unicode в поток байтов. Если вы используете предложение Jiri о потоке в кодеках, вы можете написать Unicode напрямую, в противном случае вам придется перекодировать строку Unicode в байты вручную.

Лучше для целей регистрации было бы просто выплюнуть repr () переменной. Тогда вам не нужно беспокоиться о существовании там символов Unicode, новых строк или других нежелательных символов:

name= 'w\xc3\xb6rner'.decode('utf-8')
file.write('Name: %r\n' % name)

Name: u'w\xf6rner'
...