Почему Python 2.x генерирует исключение с форматированием строки + unicode?

У меня есть следующий код. Последняя строка вызывает ошибку. Почему это?

class Foo(object): def __unicode__(self): return u'\u6797\u89ba\u6c11\u8b1d\u51b0\u5fc3\u6545\u5c45' def __str__(self): return self.__unicode__().encode('utf-8') print "this works %s" % (u'asdf') print "this works %s" % (Foo(),) print "this works %s %s" % (Foo(), 'asdf') print print "this also works {0} {1}".format(Foo(), u'asdf') print print "this should break %s %s" % (Foo(), u'asdf') 

Ошибка: «UnicodeDecodeError:« ascii »кодек не может декодировать байт 0xe6 в позиции 18: порядковый номер не в диапазоне (128)»

One Solution collect form web for “Почему Python 2.x генерирует исключение с форматированием строки + unicode?”

Python 2 неявно будет пытаться кодировать значения unicode для строк при смешивании unicode и строковых объектов, или он будет пытаться и декодировать строки байтов в unicode.

Вы смешиваете unicode, байтовые строки и пользовательский объект, и вы запускаете последовательность кодировок и декодирования, которые не смешиваются.

В этом случае ваше значение Foo() интерполируется как строка (используется str(Foo()) ), а интерполяция u'asdf' запускает декодирование шаблона до сих пор (так что с UTF-8 Foo() значение) для интерполяции строки юникода. Это декодирование \xe6\x9e\x97 неудачно, так как кодек ASCII не может декодировать последовательность \xe6\x9e\x97 UTF-8, уже интерполированную.

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

Явное преобразование в unicode() работает:

 >>> print "this should break %s %s" % (unicode(Foo()), u'asdf') this should break 林覺民謝冰心故居 asdf 

поскольку вывод преобразуется в строку юникода:

 >>> "this should break %s %s" % (unicode(Foo()), u'asdf') u'this should break \u6797\u89ba\u6c11\u8b1d\u51b0\u5fc3\u6545\u5c45 asdf' 

в противном случае вы закончите с байтовой строкой:

 >>> "this should break %s %s" % (Foo(), 'asdf') 'this should break \xe6\x9e\x97\xe8\xa6\xba\xe6\xb0\x91\xe8\xac\x9d\xe5\x86\xb0\xe5\xbf\x83\xe6\x95\x85\xe5\xb1\x85 asdf' 

(обратите внимание, что asdf остается в байтах).

Кроме того, используйте шаблон юникода:

 >>> u"this should break %s %s" % (Foo(), u'asdf') u'this should break \u6797\u89ba\u6c11\u8b1d\u51b0\u5fc3\u6545\u5c45 asdf' 
  • Использование функций unicode () и encode () в Python
  • Scrapy xpath utf-8 литералы
  • UnicodeEncodeError при записи в файл
  • Есть ли константа Python для Unicode-пробелов?
  • Идентификатор имени ISO 8859-1 не декодируется
  • Выход Unicode в stdout Python при запуске из cmd.exe
  • Преобразование объекта unicode в латинскую строку с объектами
  • Словарь Python Gensim word2vec
  • chr () эквивалент, возвращающий объект байтов, в py3k
  • Python + PostgreSQL + странная ошибка ascii = UTF8
  • Декодирование объектов HTML с помощью Python
  • Python - лучший язык программирования в мире.