Zanurkuj w Pythonie/Praca z unikodem

Z Wikibooks, biblioteki wolnych podręczników.

[edytuj] Praca z unikodem

Unikodowymi napisami posługujemy się w identyczny sposób jak normalnymi łańcuchami znaków.

Przykład. Posługiwanie się unikodem
>>> errmsg = u'Nie można otworzyć pliku'  #(1)
>>> print errmsg                         #(2)
Nie można otworzyć pliku
>>> print errmsg + u', brak dostępu.'   #(3)
Nie można otworzyć pliku, brak dostępu.
>>> errmsg.split()                      #(4)
[u'Nie', u'mo\u017cna', u'otworzy\u0107', u'pliku']
>>> print u"Błąd: %s"%errmsg
Błąd: Nie można otworzyć pliku

  1. Tworzymy unikodowy napis i przypisujemy go do zmiennej errmsg.
  2. Wypisując dowolny unikod, Python go zakoduje w taki sposób, aby był zgodny z kodowaniem znaków wyjścia, a więc dany napis zostanie zawsze wypisany z polskimi znakami.
  3. Z unikodem operujemy identycznie, jak z innymi łańcuchami znaków. Możemy na przykład dwa unikody ze sobą łączyć.
  4. Możemy także podzielić unikod na listę.
  5. Ponadto, podobnie jak w przypadku standardowego łancucha znaków, możemy też unikod formatować.


[edytuj] Unikod a łańcuchy znaków

Funkcjonalność unikodu możemy łączyć ze standardowymi łańcuchami znaków, o ile z operacji tych jasno wynika, co chcemy osiągnąć.

Przykład. Unikod w połączeniu z łańcuchami znaków
>>> file = 'myfile.txt'
>>> errmsg + ' ' + file         #(1)
u'Nie mo\u017cna otworzy\u0107 pliku myfile.txt'
>>> "%s %s"%(errmsg, file)      #(2)
u'Nie mo\u017cna otworzy\u0107 pliku myfile.txt'
>>> errmsg + ', brak dostępu.'   #(3)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc4 in position 11: ordinal not in range(128)
>>> "Błąd: %s"%errmsg           #(4)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc4 in position 11: ordinal not in range(128)
  1. Unikod możemy połączyć z łańcuchem znaków. Powstaje nowy napis unikodowy.
  2. Możemy formatować łańcuch znaków korzystając z unikodowych wartości. Tu także powstaje nowy unikod.
  3. Python rzucił wyjątek; nie potrafi przekształcić napisu ', brak dostępu' na napis unikodowy. Z unikodem możemy łączyć jedynie łańcuchy znaków w systemie ASCII (czyli zawierające jedynie angielskie litery i kilka innych symboli np. przecinki, kropki itp.). W tym przypadku Python nie wie, z jakiego kodowania korzystamy.
  4. Tutaj mamy analogiczną sytuację. Python nie potrafi przekształcić napisu 'Błąd: %s' na unikod i rzuca wyjątek.


Python zakłada, że kodowaniem wszystkich łańcuchów znaków jest ASCII [1], dlatego jeśli mieszamy tekst unikodowy z łańcuchami znaków, powinniśmy dopilnować, aby łańcuchy znaków zawierały znaki należące do ASCII (czyli nie mogą posiadać polskich znaków).

[edytuj] encode i decode

A co wtedy, gdy chcemy przekształcić unikodowy napis na łańcuch znaków? Łańcuchy znaków są jakoś zakodowane, więc aby stworzyć łańcuch znaków, musimy go na coś zakodować np. ISO 8859-2, czy też UTF-8. W tym celu korzystamy z metody encode unikodu.

Przykład. Metoda encode
>>> errmsg.encode('iso-8859-2')     #(1)
'Nie mo\xbfna otworzy\xe6 pliku'
>>> errmsg.encode('utf-8')
'Nie mo\xc5\xbcna otworzy\xc4\x87 pliku' #(2)

  1. Za pomocą metody encode informujemy Pythona na jakie kodowanie znaków chcemy zakodować dany łańcuch znaków. W tym przypadku otrzymujemy łańcuch znaków zakodowany w systemie ISO 8859-2.
  2. Tutaj otrzymujemy ten sam napis, ale zakodowany w systemie UTF-8.


Operację odwrotną, czyli odkodowania, wykonujemy za pomocą funkcji decode. Na przykład:

Przykład. Metoda decode
>>> msg = errmsg.encode('utf-8')       #(1)
>>> msg.decode('utf-8')                #(2)
u'Nie mo\u017cna otworzy\u0107 pliku'
>>> print msg.decode('utf-8')
Nie można otworzyć pliku

  1. W tym miejscu zakodowaliśmy napis errmsg na UTF-8.
  2. Za pomocą metody decode odkodowaliśmy zakodowany łańcuch znaków i zwrócony został unikod.


Porada Łańcuch znaków przechowuje znaki w zakodowanej postaci np. w systemie UTF-8, ISO 8859-1, czy ISO 8859-4; może być wieloznaczny. Natomiast unikod jest jednoznaczny, więc nie jest zakodowany w tego typu systemach kodowania. Ponieważ łańcuch znaków jest zakodowany, musimy odkodować (za pomocą decode), aby otrzymać niezakodowany unikod. Z kolei unikod, ponieważ jest niezakodowany, musimy zakodować (za pomocą encode), aby otrzymać zakodowany łańcuch znaków.

Przypisy


  1. Istnieje możliwość zmiany domyślnego kodowania łańcuchów znaków na inny, ale nie powinno się tego robić. Zmiana domyślnego kodowania wprowadza pewne komplikacje i sprawia, że programy stają się nieprzenośne, dlatego nie będziemy tego opisywać w tej książce.