Problem polega na tym, że dzwonisz encode
na str
obiekt.
str
to ciąg bajtów, zwykle reprezentujący tekst zakodowany w taki sposób, jak UTF-8. Kiedy dzwonisz do encode
w tym celu najpierw musi zostać zdekodowany z powrotem do tekstu, aby tekst mógł zostać ponownie zakodowany. Domyślnie Python robi to, wywołując s.decode(sys.getgetdefaultencoding())
i getdefaultencoding()
zwykle zwraca 'ascii'
.
Mówisz więc o tekście zakodowanym w UTF-8, dekodując go tak, jakby był to ASCII, a następnie ponownie kodując w UTF-8.
Ogólnym rozwiązaniem jest jawne wywołanie decode
z właściwym kodowaniem, zamiast pozwolić Pythonowi na użycie domyślnego, a następnie encode
wynik.
Ale kiedy właściwe kodowanie jest już tym, którego szukasz, łatwiejszym rozwiązaniem jest pominięcie .decode('utf-8').encode('utf-8')
i po prostu użyj UTF-8 str
jako UTF-8 str
że już jest.
Lub, alternatywnie, jeśli twój wrapper MySQL ma funkcję pozwalającą ci określić kodowanie i odzyskać unicode
wartości dla CHAR
/VARCHAR
/TEXT
kolumny zamiast str
wartości (np. w MySQLdb podajesz use_unicode=True
do connect
zadzwoń lub charset='UTF-8'
jeśli twoja baza danych jest zbyt stara, aby ją automatycznie wykryć), po prostu to zrób. Wtedy będziesz mieć unicode
obiektów i możesz wywołać .encode('utf-8')
na nich.
Ogólnie rzecz biorąc, najlepszym sposobem radzenia sobie z problemami Unicode jest ten ostatni — zdekoduj wszystko tak wcześnie, jak to możliwe, wykonaj całe przetwarzanie w Unicode, a następnie zakoduj tak późno, jak to możliwe. Ale tak czy inaczej, musisz być konsekwentny. Nie dzwoń do str
na czymś, co może być unicode
; nie łącz str
literał do unicode
lub przekaż jeden do jego replace
metoda; itp. Za każdym razem, gdy miksujesz i dopasujesz, Python dokona konwersji niejawnie, używając domyślnego kodowania, które prawie nigdy nie jest tym, czego chcesz.
Na marginesie, jest to jedna z wielu rzeczy, w których pomagają zmiany Unicode w Pythonie 3.x. Najpierw str
jest teraz tekstem Unicode, a nie zakodowanymi bajtami. Co ważniejsze, jeśli masz zakodowane bajty, np. w bytes
obiekt, wywołując encode
da ci AttributeError
zamiast próbować po cichu dekodować, aby mógł ponownie zakodować. Podobnie, próba mieszania i dopasowywania Unicode i bajtów da oczywisty TypeError
, zamiast niejawnej konwersji, która w niektórych przypadkach się udaje i daje tajemniczą wiadomość o kodowaniu lub dekodowaniu, o które nie prosiłeś w innych.