Głównym źródłem problemów, które miałem podczas pracy z ciągami znaków Unicode, jest mieszanie ciągów zakodowanych w utf-8 z ciągami znaków Unicode.
Na przykład rozważ następujące skrypty.
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
Wynik działania python one.pyto:
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)
W tym przykładzie two.namejest to ciąg zakodowany w formacie UTF-8 (nie Unicode), ponieważ nie został zaimportowany unicode_literals, i one.namejest to ciąg znaków Unicode. Kiedy mieszasz oba, Python próbuje zdekodować zakodowany ciąg (zakładając, że jest to ascii) i przekonwertować go na Unicode, ale kończy się to niepowodzeniem. Zadziałałoby, gdybyś to zrobił print name + two.name.decode('utf-8').
To samo może się zdarzyć, jeśli zakodujesz ciąg i spróbujesz go później zmiksować. Na przykład to działa:
# encoding: utf-8
html = '<html><body>helló wörld</body></html>'
if isinstance(html, unicode):
html = html.encode('utf-8')
print 'DEBUG: %s' % html
Wynik:
DEBUG: <html><body>helló wörld</body></html>
Ale po dodaniu import unicode_literalsNIE:
# 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
Wynik:
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)
Nie udaje się, ponieważ 'DEBUG: %s'jest to ciąg znaków Unicode i dlatego Python próbuje zdekodować html. Kilka sposobów na naprawienie wydruku to robi print str('DEBUG: %s') % htmllub print 'DEBUG: %s' % html.decode('utf-8').
Mam nadzieję, że pomoże ci to zrozumieć potencjalne problemy podczas używania ciągów Unicode.
decode()rozwiązania zamiast rozwiązaństr()lubencode(): im częściej używasz obiektów Unicode, tym jaśniejszy jest kod, ponieważ to, czego chcesz, to manipulowanie ciągami znaków, a nie tablicami bajtów z zewnętrznie implikowanym kodowaniem.