Основным источником проблем, с которыми я сталкивался при работе со строками Unicode, является смешивание строк в кодировке UTF-8 со строками Unicode.
Например, рассмотрим следующие сценарии.
two.py
# encoding: utf-8
name = 'helló wörld from two'
one.py
# encoding: utf-8
from __future__ import unicode_literals
import two
name = 'helló wörld from one'
print name + two.name
Результат работы python one.py
:
Traceback (most recent call last):
File "one.py", line 5, in <module>
print name + two.name
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 4: ordinal not in range(128)
В этом примере two.name
- это строка в кодировке utf-8 (не в Юникоде), поскольку она не импортировала unicode_literals
, а one.name
- это строка в Юникоде. Когда вы смешиваете оба, python пытается декодировать закодированную строку (предполагая, что это ascii) и преобразовывает ее в unicode, и терпит неудачу. Это сработало бы, если бы вы сделали print name + two.name.decode('utf-8')
.
То же самое может произойти, если вы закодируете строку и попытаетесь смешать их позже.
Например, это работает:
# encoding: utf-8
html = '<html><body>helló wörld</body></html>'
if isinstance(html, unicode):
html = html.encode('utf-8')
print 'DEBUG: %s' % html
Выход:
DEBUG: <html><body>helló wörld</body></html>
Но после добавления import unicode_literals
это НЕ:
# encoding: utf-8
from __future__ import unicode_literals
html = '<html><body>helló wörld</body></html>'
if isinstance(html, unicode):
html = html.encode('utf-8')
print 'DEBUG: %s' % html
Выход:
Traceback (most recent call last):
File "test.py", line 6, in <module>
print 'DEBUG: %s' % html
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 16: ordinal not in range(128)
Сбой, потому что 'DEBUG: %s'
- это строка в юникоде, и поэтому python пытается декодировать html
. Для исправления печати можно использовать несколько способов: print str('DEBUG: %s') % html
или print 'DEBUG: %s' % html.decode('utf-8')
.
.
Надеюсь, это поможет вам понять потенциальные ошибки при использовании Unicode-строк.