2011-12-03 19 views
18

Estoy analizando datos json y tratando de almacenar algunos de los datos json en la base de datos Mysql. Actualmente recibo el siguiente error de Unicode. Mi pregunta es cómo debería manejar esto.Python y MySql: Unicode y codificación

  • ¿Debo manejarlo desde el lado de la base de datos, y si es así cómo puedo modificar mi tabla para hacerlo?
  • ¿Debo manejarlo desde el lado de python?

Aquí es mi estructura de la tabla

CREATE TABLE yahoo_questions (
    question_id varchar(40) NOT NULL, 
    question_subj varbinary(255), 
    question_content varbinary(255), 
    question_userId varchar(40) NOT NULL, 
    question_timestamp varchar(40), 
    category_id varbinary(20) NOT NULL, 
    category_name varchar(40) NOT NULL, 
    choosen_answer varbinary(255), 
    choosen_userId varchar(40), 
    choosen_usernick varchar(40), 
    choosen_ans_timestamp varchar(40), 
    UNIQUE (question_id) 
); 

error al insertar a través de código Python: Segmento

Traceback (most recent call last): 
    File "YahooQueryData.py", line 78, in <module> 
    +"VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)", (row[2], row[5], row[6], quserId, questionTime, categoryId, categoryName, qChosenAnswer, choosenUserId, choosenNickName, choosenTimeStamp)) 
    File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/MySQLdb/cursors.py", line 159, in execute 
    query = query % db.literal(args) 
    File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/MySQLdb/connections.py", line 264, in literal 
    return self.escape(o, self.encoders) 
    File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/MySQLdb/connections.py", line 202, in unicode_literal 
    return db.literal(u.encode(unicode_literal.charset)) 
UnicodeEncodeError: 'latin-1' codec can't encode characters in position 204-230: ordinal not in range(256) 
Código Python

:

#pushing user id to the url to get full json stack 
    urlobject = urllib.urlopen(base_url.format(row[2])) 
    qnadatajson = urlobject.read() 
    data = json.loads(qnadatajson) 
cur.execute("INSERT INTO yahoo_questions (question_id, question_subj, question_content, question_userId, question_timestamp," 
      +"category_id, category_name, choosen_answer, choosen_userId, choosen_usernick, choosen_ans_timestamp)" 
      +"VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)", (row[2], row[5], row[6], quserId, questionTime, categoryId, categoryName, qChosenAnswer, choosenUserId, choosenNickName, choosenTimeStamp)) 

Estructura JSON

questions: [ 
{ 
Id: "20111201185322AA5HTDc", 
Subject: "what are the new pokemon call?", 
Content: "I used to know them I stop at dialga and palkia version and I heard there's new ones what's it call 
", 
Date: "2011-12-01 18:53:22", 
Timestamp: "1322794402", 

Lo que también hice antes de ejecutar la consulta que ejecute lo siguiente en mysql SET character_set_client = utf8

Y esto cómo las variables de MySQL parece:

mysql> SHOW variables LIKE '%character_set%'; 
+--------------------------+--------------------------------------------------------+ 
| Variable_name   | Value             | 
+--------------------------+--------------------------------------------------------+ 
| character_set_client  | utf8             | 
| character_set_connection | utf8             | 
| character_set_database | latin1             | 
| character_set_filesystem | binary             | 
| character_set_results | utf8             | 
| character_set_server  | latin1             | 
| character_set_system  | utf8             | 
| character_sets_dir  | /usr/local/mysql-5.5.10-osx10.6-x86_64/share/charsets/ | 
+--------------------------+--------------------------------------------------------+ 
8 rows in set (0.00 sec) 
+1

El habitual "obtener MySQL para aceptar UTF-8" encantamiento es asegurarse de que los nombres de los conjuntos utf8'' '' es su primera consulta al abrir la conexión. ¿Has probado eso en lugar de 'character_set_client'? (Esto es solo un comentario porque no creo que ese sea el problema aquí, basado en la salida de su var. Creo que su biblioteca MYSQLdb Python está tratando de codificar a latin-1 y no sabe que debería estar codificando a utf-8 . Verifique la documentación y vea si hay alguna forma de informarle sobre este hecho.) –

+1

Su problema es con% s, está tratando de convertir datos Unicode en una cadena. Tengo el mismo problema, simplemente no estoy seguro de cómo solucionarlo ... – bailout00

Respuesta

69

Creo que la biblioteca de Python MySQLdb no lo hace saber que se supone que codifica a utf8, y está codificando el juego de caracteres predeterminado de Python latin1.

Cuando connect() en su base de datos, pase el parámetro charset='utf8'. Esto también debería hacer innecesario un manual SET NAMES o SET character_set_client.

+4

con = mdb.connect ('localhost', 'XXXX', 'XXXX', 'XXXX', unix_socket = '/ tmp/mysql.sock' , charset = 'utf8') ¿es esto lo que quiso decir ...? –

+0

Eso es lo que quise decir. Sin embargo, ahora no estoy seguro de la documentación si necesita 'SET NAMES utf8' también o no. Yo probaría ambos. –

+1

Gracias, funcionó. –

35

En primer lugar, asegúrese de que está asignando los parámetros charset y use_unicode al hacer su conexión a MySQL:

conn = mysql.connect(host='127.0.0.1', 
        user='user', 
        passwd='passwd', 
        db='db', 
        charset='utf8', 
        use_unicode=True) 

En segundo lugar, utilice prepared statements cuando en realidad la consulta de la base de datos. A continuación se muestra un ejemplo de consulta INSERT de una cadena que contiene un carácter Unicode.

cursor.execute('INSERT INTO mytable VALUES (null, %s)',     
       ('Some string that contains unicode: ' + unichr(300),)) 
+2

Funcionó como un amuleto. tyvm – Homer6

Cuestiones relacionadas