Problém je v tom, že voláte encode
na str
objekt.
A str
je bajtový řetězec, který obvykle představuje text zakódovaný nějakým způsobem jako UTF-8. Když zavoláte encode
na to musí být nejprve dekódován zpět na text, aby bylo možné text znovu zakódovat. Ve výchozím nastavení to Python dělá voláním s.decode(sys.getgetdefaultencoding())
a getdefaultencoding()
obvykle vrací 'ascii'
.
Takže mluvíte o textu zakódovaném v UTF-8, dekódujete jej, jako by to bylo ASCII, a poté jej znovu zakódujete do UTF-8.
Obecným řešením je explicitně zavolat decode
se správným kódováním, místo aby Python použil výchozí a poté encode
výsledek.
Ale když už je správné kódování takové, jaké chcete, jednodušším řešením je přeskočit .decode('utf-8').encode('utf-8')
a stačí použít UTF-8 str
jako UTF-8 str
že už je.
Nebo, pokud má váš obal MySQL funkci, která vám umožní zadat kódování a získat zpět unicode
hodnoty pro CHAR
/VARCHAR
/TEXT
sloupců místo str
hodnoty (např. v MySQLdb předáte use_unicode=True
k connect
volání nebo charset='UTF-8'
pokud je vaše databáze příliš stará na to, aby ji automaticky detekovala), udělejte to. Pak budete mít unicode
objektů a můžete zavolat .encode('utf-8')
na nich.
Obecně platí, že nejlepší způsob, jak se vypořádat s problémy Unicode, je ten poslední – vše dekódovat co nejdříve, provést veškeré zpracování v Unicode a pak kódovat co nejpozději. Ale v každém případě musíte být důslední. Nevolejte str
na něčem, co může být unicode
; nezřetězujte str
doslovný k unicode
nebo předejte jeden jeho replace
metoda; atd. Kdykoli budete kombinovat a porovnávat, Python za vás implicitně převede pomocí vašeho výchozího kódování, které téměř nikdy není to, co chcete.
Jako vedlejší poznámku, toto je jedna z mnoha věcí, se kterou změny Unicode Pythonu 3.x pomáhají. Nejprve str
je nyní text Unicode, nikoli kódované bajty. Ještě důležitější je, pokud máte zakódované bajty, např. v bytes
objekt volající encode
zobrazí AttributeError
místo pokusu o tiché dekódování, aby mohl znovu zakódovat. A podobně, když se pokusíte kombinovat Unicode a bajty, získáte zřejmou TypeError
, namísto implicitní konverze, která v některých případech uspěje a poskytne tajemnou zprávu o kódování nebo dekódování, o které jste v jiných nepožádali.