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.py
to:
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.name
jest to ciąg zakodowany w formacie UTF-8 (nie Unicode), ponieważ nie został zaimportowany unicode_literals
, i one.name
jest 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_literals
NIE:
# 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') % html
lub 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.