El mensaje de error
UnicodeEncodeError: 'latin-1' codec can't encode character u'\u2026'
in position 35: ordinal not in range(256)
parece indicar que algún código del lenguaje Python está intentando convertir el carácter \u2026
en una cadena Latin-1 (ISO8859-1), y está fallando. No sorprende, ese carácter es U+2026 HORIZONTAL ELLIPSIS
, que no tiene un único carácter equivalente en ISO8859-1.
Solucionaste el problema agregando la consulta ?charset=utf8
en su llamada de conexión SQLAlchemy:
import sqlalchemy
from sqlalchemy import create_engine, MetaData, Table
db = create_engine('mysql://user:[email protected]/db?charset=utf8')
La sección URL de base de datos
de la documentación de SQLAlchemy nos dice que una URL que comienza con mysql
indica un dialecto MySQL, usando mysql-python
conductor.
La siguiente sección, DBAPI personalizado argumentos connect() , nos dice que los argumentos de consulta se pasan al DBAPI subyacente.
Entonces, ¿qué significa mysql-python
controlador marca de un parámetro {charset: 'utf8'}
? Sección Funciones y atributos
de su documentación dice del charset
atributo "...Si está presente, el conjunto de caracteres de conexión se cambiará a este conjunto de caracteres, si no son iguales".
Para averiguar qué significa el conjunto de caracteres de conexión, recurrimos a
Dado que el mensaje de error que informó parece un Python en lugar de un mensaje de error de SQL, especularé que algo en SQLAlchemy o mysql-python está intentando convertir la consulta a una codificación de conexión predeterminada de latin-1
antes de enviarlo. Esto es lo que desencadena el error. Sin embargo, la cadena de consulta ?charset=utf8
en tu connect()
llamada cambia la codificación de la conexión y U+2026 HORIZONTAL ELLIPSIS
es capaz de pasar.
Actualización: también pregunta, "si elimino la opción de juego de caracteres y luego codifico la descripción usando .encode('cp1252') funcionará bien. ¿Cómo es que una elipsis puede pasar con cp1252 pero no con Unicode?"
La codificación cp1252
tiene
un carácter de puntos suspensivos horizontales en el valor de byte \x85
. Por lo tanto, es posible codificar una cadena Unicode que contenga U+2026 HORIZONTAL ELLIPSIS
en cp1252 sin error.
Recuerde también que en Python, las cadenas Unicode y las cadenas de bytes son dos tipos de datos diferentes. Es razonable especular que MySQLdb podría tener una política de enviar solo cadenas de bytes a través de una conexión SQL. Por lo tanto, codificaría una consulta recibida como una cadena Unicode en una cadena de bytes, pero dejaría una consulta recibida como una cadena de bytes sola. (Esto es especulación, no he mirado el código fuente).
En el rastreo que publicaste, las últimas dos líneas (las más cercanas a donde ocurrió el error) muestran los nombres de los métodos literal
, seguido de unicode_literal
. Eso tiende a respaldar la teoría de que MySQLdb está codificando la consulta que recibe como una cadena Unicode en una cadena de bytes.
Cuando codifica la cadena de consulta usted mismo, omite la parte de MySQLdb que hace esta codificación de manera diferente. Tenga en cuenta, sin embargo, que si codifica la cadena de consulta de manera diferente a la que requiere el juego de caracteres de conexión de MySQL, tendrá una discrepancia de codificación y es probable que su texto se almacene de forma incorrecta.