El problema es que estás llamando a encode
en una str
objeto.
Una str
es una cadena de bytes, que generalmente representa texto codificado de alguna manera como UTF-8. Cuando llamas a encode
en eso, primero tiene que decodificarse de nuevo a texto, para que el texto pueda volver a codificarse. De forma predeterminada, Python hace eso llamando a s.decode(sys.getgetdefaultencoding())
y getdefaultencoding()
normalmente devuelve 'ascii'
.
Por lo tanto, está hablando de texto codificado en UTF-8, decodificándolo como si fuera ASCII y luego recodificándolo en UTF-8.
La solución general es llamar explícitamente a decode
con la codificación correcta, en lugar de dejar que Python use el valor predeterminado, y luego encode
el resultado.
Pero cuando la codificación correcta ya es la que desea, la solución más fácil es omitir .decode('utf-8').encode('utf-8')
y simplemente use el UTF-8 str
como UTF-8 str
que ya lo es.
O, alternativamente, si su contenedor MySQL tiene una función que le permite especificar una codificación y recuperar unicode
valores para CHAR
/VARCHAR
/TEXT
columnas en lugar de str
valores (por ejemplo, en MySQLdb, pasa use_unicode=True
al connect
llamada, o charset='UTF-8'
si su base de datos es demasiado antigua para detectarla automáticamente), simplemente hágalo. Entonces tendrás unicode
objetos, y puede llamar a .encode('utf-8')
en ellos.
En general, la mejor manera de lidiar con los problemas de Unicode es la última:decodificar todo lo antes posible, realizar todo el procesamiento en Unicode y luego codificar lo más tarde posible. Pero de cualquier manera, tienes que ser constante. No llamar a str
en algo que podría ser un unicode
; no concatenes un str
literal a un unicode
o pasar uno a su replace
método; etc. Cada vez que mezcle y combine, Python se convertirá implícitamente por usted, utilizando su codificación predeterminada, que casi nunca es lo que desea.
Como nota al margen, esta es una de las muchas cosas con las que ayudan los cambios Unicode de Python 3.x. Primero, str
ahora es texto Unicode, no bytes codificados. Más importante aún, si tiene bytes codificados, por ejemplo, en un bytes
objeto, llamando a encode
le dará un AttributeError
en lugar de intentar decodificar en silencio para que pueda volver a codificar. Y, de manera similar, tratar de mezclar y combinar Unicode y bytes le dará un obvio TypeError
, en lugar de una conversión implícita que tiene éxito en algunos casos y da un mensaje críptico sobre una codificación o decodificación que no solicitó en otros.