2011-12-03 17 views
18

Parsuję dane json i próbuję przechowywać niektóre z danych json w bazie danych Mysql. Obecnie otrzymuję następujący błąd Unicode. Moje pytanie brzmi: jak mam sobie z tym poradzić.Python i MySql: Unicode i kodowanie

  • Czy powinienem sobie z tym poradzić od strony bazy danych, a jeśli tak, to w jaki sposób mogę zmodyfikować mój stół, aby to zrobić?
  • Czy powinienem obsłużyć go od strony Pythona?

Oto moja struktura tabeli

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

Błąd podczas wstawiania za pomocą kodu Pythona: segmentu

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) 

kodu Pythona:

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

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

Co Zrobiłem też przed uruchomieniem kwerendy I wykonać następujące operacje na mysql SET character_set_client = utf8

I to jak zmienne mysql wygląda następująco:

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

Zwykła „get mysql przyjąć utf8” zaklęcie jest upewnienie się, że 'utf8'' Ustaw nazwy” jest twój pierwszy zapytanie przy otwarciu połączenia. Czy próbowałeś tego zamiast 'character_set_client'? (To jest tylko komentarz, ponieważ nie sądzę, że jest to problem tutaj, na podstawie twojego wyjścia var.) Myślę, że twoja biblioteka Python MYSQLdb próbuje kodować do latin-1 i nie wie, że powinna ona kodować do utf-8 Sprawdź dokumentację i sprawdź, czy jest jakiś sposób poinformowania go o tym fakcie.) –

+1

Twój problem dotyczy% s, próbujesz przekonwertować dane Unicode na ciąg znaków. Mam ten sam problem, tylko nie wiem jak to naprawić ... – bailout00

Odpowiedz

69

myślę że MySQLdb python library nie wiadomo, że ma kodować do utf8 i koduje domyślny zestaw znaków zdefiniowany przez pythona latin1.

Po przesłaniu connect() do bazy danych należy podać parametr charset='utf8'. Powinno to również uczynić instrukcję niepotrzebną.

+4

con = mdb.connect ('localhost', 'XXXX', 'XXXX', 'XXXX', unix_socket = '/ tmp/mysql.sock' , charset = 'utf8') czy to masz na myśli ...? –

+0

To właśnie miałem na myśli. Jednak nie jestem teraz pewien z dokumentacji, czy musisz "SET NAMES utf8" również, czy nie. Chciałbym spróbować obu. –

+1

Dzięki temu zadziałało. –

35

Po pierwsze, upewnij się, że przypisywanie parametrów charset i use_unicode po dokonaniu połączenia MySQL:

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

Po drugie, należy prepared statements gdy faktycznie zapytań do bazy danych. Poniżej znajduje się przykład WSTAW zapytania o ciąg zawierający znak Unicode.

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

Pracował jak urok. tyvm – Homer6