2010-10-15 13 views
51

¿Qué podría estar causando este error cuando intento insertar un carácter extraño en la base de datos?UnicodeEncodeError: el códec 'latin-1' no puede codificar el carácter

>>UnicodeEncodeError: 'latin-1' codec can't encode character u'\u201c' in position 0: ordinal not in range(256) 

¿Y cómo lo resuelvo?

Gracias!

+27

db = MySQLdb.connect (host = "localhost", user = "raíz", passwd = "", db = "testdb", use_unicode = True, charset = "UTF-8") –

Respuesta

44

Carácter U + 201C La marca de comilla doble izquierda no está presente en la codificación Latin-1 (ISO-8859-1).

It es presente en la página de códigos 1252 (Western European). Esta es una codificación específica de Windows que está basada en ISO-8859-1 pero que pone caracteres adicionales en el rango 0x80-0x9F. La página de códigos 1252 a menudo se confunde con ISO-8859-1, y es un comportamiento molesto pero ahora estándar del navegador web que si sirve sus páginas como ISO-8859-1, el navegador las tratará como cp1252. Sin embargo, lo que realmente son dos codificaciones distintas:

>>> u'He said \u201CHello\u201D'.encode('iso-8859-1') 
UnicodeEncodeError 
>>> u'He said \u201CHello\u201D'.encode('cp1252') 
'He said \x93Hello\x94' 

Si está utilizando la base de datos sólo como una tienda de bytes, que puede utilizar para codificar CP1252 y otros personajes presentes en la página de códigos de Windows occidental. Pero aún otros caracteres Unicode que no están presentes en cp1252 causarán errores.

Puede usar encode(..., 'ignore') para suprimir los errores al deshacerse de los caracteres, pero realmente en este siglo debe usar UTF-8 tanto en su base de datos como en sus páginas. Esta codificación permite que cualquier personaje sea utilizado. También debería decirle a MySQL que está utilizando cadenas UTF-8 (estableciendo la conexión de la base de datos y la intercalación en las columnas de cadena), de modo que pueda hacer una comparación y clasificación que no distinga entre mayúsculas y minúsculas.

+0

¿No es 'cp1252' un superconjunto estricto de ISO-8859-1? Es decir. cuando los navegadores reciben una página ISO-8859-1, pueden renderizarla como si fuera CP1252 porque de todos modos no habrá caracteres del rango '0x80-0x9F'. – MSalters

+3

No, los bytes 0x80-0x9F tienen asignaciones reales en ISO-8859-1, que son anuladas por las adiciones de cp1252, por lo que no es un superconjunto. Se asignan exactamente a los caracteres Unicode U + 0080-U + 009F, que son una selección de caracteres de control. Son caracteres de control que no se usan mucho y por eso los navegadores se salieron con la suya, pero es molesto cuando intentas convertir secuencias de bytes como Unicode. – bobince

+0

La única vez que he visto caracteres en el rango U + 0080-U + 009F en un archivo codificado como ISO-8859-1 o UTF-8 resultó de un payaso que concatenó un grupo de archivos, algunos de los cuales estaban codificados en cp850 y luego transcodificando el desorden resultante de "latin1" a UTF-8. El borrador de la especificación HTML5 está considerando santificar ese comportamiento muy práctico del navegador (y un montón de casos similares) - ver http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html# codificaciones de caracteres-0 –

3

Está intentando almacenar un punto de código Unicode \u201c utilizando una codificación ISO-8859-1/Latin-1 que no puede describir ese punto de código. O bien es posible que deba modificar la base de datos para usar utf-8 y almacenar los datos de cadena utilizando una codificación adecuada, o puede desear desinfectar sus entradas antes de almacenar el contenido; es decir, usando something like Sam Ruby's excellent i18n guide. Eso habla sobre los problemas que windows-1252 puede causar, y sugiere cómo procesarlo, además de enlaces al código de muestra.

1

Latin-1 (también conocido como ISO 8859-1) es un único esquema de codificación de caracteres octeto, y usted no puede caber \u201c () en un byte.

¿Quería usar la codificación UTF-8?

+1

Latin- 1 codifica _caracteres Unicode específicos, simplemente no ese. No importa si \ u201c no puede caber en un byte. Windows-1252 es un esquema de codificación de un solo octeto también, y _hace_ incluyendo \ u201c. –

+0

cp1253 (también conocido como windows-1253) es también un esquema de codificación de caracteres de un solo octeto, y aún '\ u0391' se ajusta bien en un byte (específicamente, byte 193). Usted * podría * querer echar un vistazo a [ese] (http://stackoverflow.com/questions/368805/python-unicodedecodeerror-am-i-misunderstanding-encode/370199#370199); la gente lo ha encontrado útil. – tzot

+0

Unicode incorpora glifos Latin-1/cp1253 en puntos de código de 16 bits. Me sorprende que los comentarios parezcan reclamar lo contrario. – msw

17

Espero que su base de datos sea al menos UTF-8. Luego deberá ejecutar yourstring.encode('utf-8') antes de intentar ponerlo en la base de datos.

+0

¡respuesta muy útil! ¡Gracias! –

66

Me encontré con este mismo problema cuando uso el módulo Python MySQLdb. Desde MySQL le permitirá almacenar casi cualquier dato binario que desea en un campo de texto sin tener en cuenta el conjunto de caracteres, encontré mi solución aquí:

Using UTF8 with Python MySQLdb

Editar: Presupuesto de la URL anterior para satisfacer la solicitud en el primer comentario...

"UnicodeEncodeError:'latin-1' codec can't encode character ..."

This is because MySQLdb normally tries to encode everythin to latin-1. This can be fixed by executing the following commands right after you've etablished the connection:

db.set_character_set('utf8') 
dbc.execute('SET NAMES utf8;') 
dbc.execute('SET CHARACTER SET utf8;') 
dbc.execute('SET character_set_connection=utf8;') 

"db" is the result of MySQLdb.connect() , and "dbc" is the result of db.cursor() .

+0

Se sugiere que la parte relevante de un elemento vinculado se proporcione en la respuesta.El enlace para leer más es excelente, pero intente mostrar un resumen ejecutivo en su respuesta, por así decirlo :) – Fluffeh

+0

@Fluffeh Y así fue. – CatShoes

+0

@CatShoes Y se realizó un voto positivo :) – Fluffeh

-2

Python: Usted tendrá que añadir # - * - coding: UTF-8 - * - (quitar los espacios alrededor *) a la primera línea de la pitón archivo. y luego agregue lo siguiente al texto para codificar: .encode ('ascii', 'xmlcharrefreplace'). Esto reemplazará todos los caracteres Unicode con su equivalente ASCII.

10

La mejor solución es charset

  1. conjunto de MySQL a 'UTF-8'
  2. gusta este comentario (añadir use_unicode=True y charset="utf8")

    db = MySQLdb.connect(host="localhost", user = "root", passwd = "", db = "testdb", use_unicode=True, charset="utf8") – KyungHoon Kim Mar 13 '14 at 17:04

detalles, véase:

class Connection(_mysql.connection): 

    """MySQL Database Connection Object""" 

    default_cursor = cursors.Cursor 

    def __init__(self, *args, **kwargs): 
     """ 

     Create a connection to the database. It is strongly recommended 
     that you only use keyword parameters. Consult the MySQL C API 
     documentation for more information. 

     host 
      string, host to connect 

     user 
      string, user to connect as 

     passwd 
      string, password to use 

     db 
      string, database to use 

     port 
      integer, TCP/IP port to connect to 

     unix_socket 
      string, location of unix_socket to use 

     conv 
      conversion dictionary, see MySQLdb.converters 

     connect_timeout 
      number of seconds to wait before the connection attempt 
      fails. 

     compress 
      if set, compression is enabled 

     named_pipe 
      if set, a named pipe is used to connect (Windows only) 

     init_command 
      command which is run once the connection is created 

     read_default_file 
      file from which default client values are read 

     read_default_group 
      configuration group to use from the default file 

     cursorclass 
      class object, used to create cursors (keyword only) 

     use_unicode 
      If True, text-like columns are returned as unicode objects 
      using the connection's character set. Otherwise, text-like 
      columns are returned as strings. columns are returned as 
      normal strings. Unicode objects will always be encoded to 
      the connection's character set regardless of this setting. 

     charset 
      If supplied, the connection character set will be changed 
      to this character set (MySQL-4.1 and newer). This implies 
      use_unicode=True. 

     sql_mode 
      If supplied, the session SQL mode will be changed to this 
      setting (MySQL-4.1 and newer). For more details and legal 
      values, see the MySQL documentation. 

     client_flag 
      integer, flags to use or 0 
      (see MySQL docs or constants/CLIENTS.py) 

     ssl 
      dictionary or mapping, contains SSL connection parameters; 
      see the MySQL documentation for more details 
      (mysql_ssl_set()). If this is set, and the client does not 
      support SSL, NotSupportedError will be raised. 

     local_infile 
      integer, non-zero enables LOAD LOCAL INFILE; zero disables 

     autocommit 
      If False (default), autocommit is disabled. 
      If True, autocommit is enabled. 
      If None, autocommit isn't set and server default is used. 

     There are a number of undocumented, non-standard methods. See the 
     documentation for the MySQL C API for some hints on what they do. 

     """ 
+0

Esta respuesta necesita más votos positivos. Esta es una solución limpia que borra la capa de aplicación de los gastos generales de codificación innecesarios. – yeaske

2

Los usuarios de SQLAlchemy pueden simplemente especificar su campo como convert_unicode=True.

Ejemplo: sqlalchemy.String(1000, convert_unicode=True)

SQLAlchemy simplemente aceptar objetos Unicode y devolverlos de nuevo, la manipulación de la codificación en sí.

Docs

Cuestiones relacionadas