Основне джерело проблем, з якими я працював з рядками 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), оскільки вона не імпортувала unicode_literals
, і one.name
є рядком unicode. Коли ви змішуєте обидва, 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'
це рядок unicode, і тому python намагається розшифрувати html
. Кілька способів виправити друк - це print str('DEBUG: %s') % html
або print 'DEBUG: %s' % html.decode('utf-8')
.
Я сподіваюсь, що це допоможе вам зрозуміти потенційні проблеми при використанні рядків Unicode.
decode()
рішеннями замість тихstr()
чиencode()
рішень: чим частіше ви використовуєте об'єкти Unicode, тим ясніше код, так що ви хочете, щоб маніпулювати рядки символів, а НЕ масиви байт з зовні неявної кодуванням.