Problemet är att du anropar encode
på en str
objekt.
En str
är en bytesträng som vanligtvis representerar text kodad på något sätt som UTF-8. När du ringer encode
på det måste den först avkodas tillbaka till text, så att texten kan kodas om. Som standard gör Python det genom att anropa s.decode(sys.getgetdefaultencoding())
, och getdefaultencoding()
returnerar vanligtvis 'ascii'
.
Så du pratar UTF-8-kodad text, avkodar den som om den vore ASCII och kodar sedan om den i UTF-8.
Den allmänna lösningen är att uttryckligen anropa decode
med rätt kodning, istället för att låta Python använda standard, och sedan encode
resultatet.
Men när rätt kodning redan är den du vill ha, är den enklare lösningen att bara hoppa över .decode('utf-8').encode('utf-8')
och använd bara UTF-8 str
som UTF-8 str
att det redan är det.
Eller, alternativt, om ditt MySQL-omslag har en funktion som låter dig specificera en kodning och få tillbaka unicode
värden för CHAR
/VARCHAR
/TEXT
kolumner istället för str
värden (t.ex. i MySQLdb skickar du use_unicode=True
till connect
samtal eller charset='UTF-8'
om din databas är för gammal för att automatiskt upptäcka den), gör bara det. Då har du unicode
objekt, och du kan anropa .encode('utf-8')
på dem.
I allmänhet är det bästa sättet att hantera Unicode-problem det sista – avkoda allt så tidigt som möjligt, gör all bearbetning i Unicode och koda sedan så sent som möjligt. Men hur som helst, du måste vara konsekvent. Ring inte str
på något som kan vara en unicode
; sammanfoga inte en str
bokstavligt till en unicode
eller skicka en till dess replace
metod; etc. Varje gång du mixar och matchar kommer Python att implicit konvertera åt dig med din standardkodning, vilket nästan aldrig är vad du vill ha.
Som en sidoanteckning är detta en av många saker som Python 3.x:s Unicode-ändringar hjälper till med. Först, str
är nu Unicode-text, inte kodad byte. Ännu viktigare, om du har kodade bytes, t.ex. i en bytes
objekt som anropar encode
ger dig en AttributeError
istället för att försöka avkoda tyst så att den kan koda om. Och om du försöker blanda och matcha Unicode och bytes får du ett uppenbart TypeError
, istället för en implicit konvertering som lyckas i vissa fall och ger ett kryptiskt meddelande om en kodning eller avkodning som du inte bett om i andra.