Il problema è che stai chiamando encode
su un str
oggetto.
Un str
è una stringa di byte, che di solito rappresenta il testo codificato in qualche modo come UTF-8. Quando chiami encode
su questo, deve prima essere decodificato in testo, in modo che il testo possa essere ricodificato. Per impostazione predefinita, Python lo fa chiamando s.decode(sys.getgetdefaultencoding())
e getdefaultencoding()
di solito restituisce 'ascii'
.
Quindi, stai parlando di testo codificato UTF-8, decodificandolo come se fosse ASCII, quindi ricodificandolo in UTF-8.
La soluzione generale è chiamare esplicitamente decode
con la giusta codifica, invece di lasciare che Python usi il default, e poi encode
il risultato.
Ma quando la codifica giusta è già quella che desideri, la soluzione più semplice è semplicemente saltare il .decode('utf-8').encode('utf-8')
e usa semplicemente UTF-8 str
come UTF-8 str
lo è già.
O, in alternativa, se il tuo wrapper MySQL ha una funzione che ti consente di specificare una codifica e tornare unicode
valori per CHAR
/VARCHAR
/TEXT
colonne invece di str
valori (ad esempio, in MySQLdb, passi use_unicode=True
al connect
call o charset='UTF-8'
se il tuo database è troppo vecchio per rilevarlo automaticamente), fallo. Allora avrai unicode
oggetti e puoi chiamare .encode('utf-8')
su di loro.
In generale, il modo migliore per affrontare i problemi Unicode è l'ultimo:decodificare tutto il prima possibile, eseguire tutte le elaborazioni in Unicode e quindi codificare il più tardi possibile. Ma in ogni caso, devi essere coerente. Non chiamare str
su qualcosa che potrebbe essere un unicode
; non concatenare un str
letterale a un unicode
oppure passane uno al suo replace
metodo; ecc. Ogni volta che mescoli e abbini, Python convertirà implicitamente per te, usando la tua codifica predefinita, che non è quasi mai quella che vuoi.
Come nota a margine, questa è una delle tante cose con cui le modifiche Unicode di Python 3.x aiutano. Innanzitutto, str
è ora testo Unicode, non byte codificati. Ancora più importante, se hai byte codificati, ad esempio, in un bytes
oggetto, chiamando encode
ti darà un AttributeError
invece di provare a decodificare silenziosamente in modo che possa ricodificare. E, allo stesso modo, provare a mescolare e abbinare Unicode e byte ti darà un ovvio TypeError
, invece di una conversione implicita che in alcuni casi riesce e fornisce un messaggio criptico su una codifica o decodifica che non hai richiesto in altri.