Problemet er, at du kalder encode
på en str
objekt.
En str
er en bytestreng, der normalt repræsenterer tekst kodet på en eller anden måde som UTF-8. Når du ringer til encode
på det, skal det først afkodes tilbage til tekst, så teksten kan omkodes. Som standard gør Python det ved at kalde s.decode(sys.getgetdefaultencoding())
, og getdefaultencoding()
returnerer normalt 'ascii'
.
Så du taler UTF-8-kodet tekst, afkoder den, som om den var ASCII, og genkoder den i UTF-8.
Den generelle løsning er eksplicit at kalde decode
med den rigtige kodning, i stedet for at lade Python bruge standarden, og derefter encode
resultatet.
Men når den rigtige kodning allerede er den, du ønsker, er den nemmere løsning bare at springe .decode('utf-8').encode('utf-8')
over og brug bare UTF-8 str
som UTF-8 str
at det allerede er.
Eller, alternativt, hvis din MySQL-indpakning har en funktion, der giver dig mulighed for at angive en kodning og få tilbage unicode
værdier for CHAR
/VARCHAR
/TEKST kolonner i stedet for
str
værdier (f.eks. i MySQLdb sender du use_unicode=True
til connect
opkald eller charset='UTF-8'
hvis din database er for gammel til at detektere den automatisk), skal du bare gøre det. Så har du unicode
objekter, og du kan kalde .encode('utf-8')
på dem.
Generelt er den bedste måde at håndtere Unicode-problemer på den sidste – afkod alt så tidligt som muligt, foretag al behandlingen i Unicode og indkod så sent som muligt. Men uanset hvad, så skal du være konsekvent. Ring ikke til str
på noget, der kan være en unicode
; lad være med at sammenkæde en str
bogstaveligt til en unicode
eller send en til dens erstat
metode; osv. Hver gang du blander og matcher, vil Python implicit konvertere for dig ved at bruge din standardkodning, som næsten aldrig er, hvad du ønsker.
Som en sidebemærkning er dette en af de mange ting, som Python 3.x's Unicode-ændringer hjælper med. Først str
er nu Unicode-tekst, ikke kodede bytes. Endnu vigtigere, hvis du har kodede bytes, f.eks. i en bytes
objekt, kalder encode
vil give dig en AttributeError
i stedet for at prøve at afkode lydløst, så det kan genkode. Og på samme måde vil forsøg på at blande og matche Unicode og bytes give dig en åbenlys TypeError
, i stedet for en implicit konvertering, der i nogle tilfælde lykkes og giver en kryptisk besked om en indkodning eller afkodning, du ikke har bedt om i andre.