web-dev-qa-db-fra.com

Python & MySql: Unicode et encodage

J'analyse les données json et j'essaie de stocker certaines des données json dans la base de données Mysql. Je reçois actuellement une erreur Unicode. Ma question est de savoir comment dois-je gérer cela.

  • Dois-je le gérer du côté de la base de données, et si oui, comment puis-je modifier ma table pour le faire?
  • Dois-je le gérer du côté python?

Voici ma structure de table

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)
);

Erreur lors de l'insertion via python:

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)

Segment de code 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))

structure 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",

Ce que j'ai également fait avant d'exécuter la requête, j'exécute ce qui suit sur mysql SET character_set_client = utf8

Et voici à quoi ressemblent les variables mysql:

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)
27
add-semi-colons

Je pense que votre bibliothèque MYSQLdb python ne sait pas qu'elle est censée encoder en utf8, et est encodée par défaut python charset défini par le système latin1.

Lorsque vous connect() dans votre base de données, passez le paramètre charset='utf8'. Cela devrait également rendre inutile un manuel SET NAMES Ou SET character_set_client.

82
Francis Avila

Tout d'abord, assurez-vous d'attribuer les charset et use_unicode paramètres lors de l'établissement de votre connexion MySQL:

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

Deuxièmement, utilisez instructions préparées lorsque vous interrogez réellement la base de données. Vous trouverez ci-dessous un exemple de requête INSERT d'une chaîne contenant un caractère unicode.

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