O problema é que você está chamando
encode
em um str
objeto. Um
str
é uma cadeia de bytes, geralmente representando texto codificado de alguma forma como UTF-8. Quando você chama encode
sobre isso, primeiro ele deve ser decodificado de volta ao texto, para que o texto possa ser recodificado. Por padrão, o Python faz isso chamando s.decode(sys.getgetdefaultencoding())
, e getdefaultencoding()
geralmente retorna 'ascii'
. Então, você está falando de texto codificado em UTF-8, decodificando-o como se fosse ASCII e, em seguida, recodificando-o em UTF-8.
A solução geral é chamar explicitamente
decode
com a codificação correta, em vez de permitir que o Python use o padrão e, em seguida, encode
o resultado. Mas quando a codificação correta já é a que você deseja, a solução mais fácil é simplesmente pular o
.decode('utf-8').encode('utf-8')
e apenas use o UTF-8 str
como o UTF-8 str
que já é. Ou, alternativamente, se o seu wrapper MySQL tiver um recurso para permitir que você especifique uma codificação e receba
unicode
valores para CHAR
/VARCHAR
/TEXT
colunas em vez de str
valores (por exemplo, no MySQLdb, você passa use_unicode=True
para connect
chamada ou charset='UTF-8'
se seu banco de dados for muito antigo para detectá-lo automaticamente), faça isso. Então você terá unicode
objetos, e você pode chamar .encode('utf-8')
neles. Em geral, a melhor maneira de lidar com problemas de Unicode é a última — decodifique tudo o mais cedo possível, faça todo o processamento em Unicode e depois codifique o mais tarde possível. Mas de qualquer forma, você tem que ser consistente. Não chame
str
em algo que pode ser um unicode
; não concatene um str
literal para um unicode
ou passe um para seu replace
método; etc. Sempre que você misturar e combinar, o Python irá converter implicitamente para você, usando sua codificação padrão, que quase nunca é o que você deseja. Como uma observação lateral, esta é uma das muitas coisas que as mudanças Unicode do Python 3.x ajudam. Primeiro,
str
agora é texto Unicode, não bytes codificados. Mais importante, se você tem bytes codificados, por exemplo, em um bytes
objeto, chamando encode
lhe dará um AttributeError
em vez de tentar decodificar silenciosamente para que possa recodificar. E, da mesma forma, tentar misturar e combinar Unicode e bytes fornecerá um óbvio TypeError
, em vez de uma conversão implícita que é bem-sucedida em alguns casos e fornece uma mensagem enigmática sobre uma codificação ou decodificação que você não solicitou em outros.