2013-02-26 34 views
33

Robię niektóre skrypty w Pythonie. Tworzę ciąg znaków, który zapisuję w pliku. Ten ciąg ma wiele danych, pochodzących z arborecencji i nazw plików katalogu. Zgodnie z convmv, wszystkie moje arbrescence jest w UTF-8.Python kodowanie utf-8

Chcę zachować wszystko w UTF-8, ponieważ zapiszę go w MySQL po. Na razie w MySQL, który jest w UTF-8, mam pewien problem z niektórymi znakami (jak é lub è - Jestem Francuzem).

Chcę, aby ten python zawsze używał ciągu znaków jako UTF-8. Czytałem trochę informacji w Internecie i to mi się podobało.

Mój skrypt zacząć z tym:

#!/usr/bin/python 
# -*- coding: utf-8 -*- 
def createIndex(): 
    import codecs 
    toUtf8=codecs.getencoder('UTF8') 
    #lot of operations & building indexSTR the string who matter 
    findex=open('config/index/music_vibration_'+date+'.index','a') 
    findex.write(codecs.BOM_UTF8) 
    findex.write(toUtf8(indexSTR)) #this bugs! 

I kiedy wykonać, oto odpowiedź: UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 2171: ordinal not in range(128)

Edit: widzę, w moim pliku, akcent są ładnie napisany. Po utworzeniu tego pliku, czytam go i zapisuję go w MySQL. Ale nie rozumiem, dlaczego, ale mam problem z kodowaniem. Moja baza danych MySQL jest w utf8 lub wydaje się być zapytaniem SQL SHOW variables LIKE 'char%' zwraca mi tylko utf8 lub binarny.

Moja funkcja wygląda tak:

#!/usr/bin/python 
# -*- coding: utf-8 -*- 

def saveIndex(index,date): 
    import MySQLdb as mdb 
    import codecs 

    sql = mdb.connect('localhost','admin','*******','music_vibration') 
    sql.charset="utf8" 
    findex=open('config/index/'+index,'r') 
    lines=findex.readlines() 
    for line in lines: 
     if line.find('#artiste') != -1: 
      artiste=line.split('[:::]') 
      artiste=artiste[1].replace('\n','') 

      c=sql.cursor() 
      c.execute('SELECT COUNT(id) AS nbr FROM artistes WHERE nom="'+artiste+'"') 
      nbr=c.fetchone() 
      if nbr[0]==0: 
       c=sql.cursor() 
       iArt+=1 
       c.execute('INSERT INTO artistes(nom,status,path) VALUES("'+artiste+'",99,"'+artiste+'/")'.encode('utf8') 

I artysty, którzy są ładnie wyświetlane w pliku pisze złe w BDD. Na czym polega problem?

+0

Twój przykładowy kod Pythona jest nieprawidłowy; występują błędy składniowe w co najmniej 2 miejscach. Czy możesz to naprawić najpierw? –

+0

Czy zapisujesz plik jako utf-8, a nie jako plik ASCII? – QuentinUK

Odpowiedz

45

Nie trzeba kodować danych o kodowaniu już. Kiedy spróbujesz to zrobić, Python najpierw spróbuje dekodować do unicode, zanim będzie mógł zakodować go z powrotem do UTF-8. To, co nie udaje się tutaj:

>>> data = u'\u00c3'   # Unicode data 
>>> data = data.encode('utf8') # encoded to UTF-8 
>>> data 
'\xc3\x83' 
>>> data.encode('utf8')   # Try to *re*-encode it 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128) 

Wystarczy napisać swoje dane bezpośrednio do pliku, nie ma nie potrzeba zakodowania już zakodowane dane.

Jeśli zamiast tego utworzysz wartości unicode, będziesz musiał je zakodować, aby można je było zapisać w pliku. Zamiast tego należy użyć wartości codecs.open(), która zwróci obiekt pliku, który zakoduje dla Ciebie kodowanie Unicode w formacie UTF-8.

też naprawdę nie chce wypisać UTF-8 BOM, chyba ty mieć wspieranie narzędzi firmy Microsoft, które nie potrafią czytać UTF-8 w inny sposób (na przykład MS Notatnik).

Dla wkładki problemu MySQL, trzeba zrobić dwie rzeczy:

  • Dodaj charset='utf8' do rozmowy MySQLdb.connect().

  • Zastosowanie unicode obiekty, nie str obiekty Podczas odpytywania lub wstawianie, ale używać parametrów SQL więc złącze MySQL może zrobić dobry uczynek dla Ciebie:

    artiste = artiste.decode('utf8') # it is already UTF8, decode to unicode 
    
    c.execute('SELECT COUNT(id) AS nbr FROM artistes WHERE nom=%s', (artiste,)) 
    
    # ... 
    
    c.execute('INSERT INTO artistes(nom,status,path) VALUES(%s, 99, %s)', (artiste, artiste + u'/')) 
    

Może faktycznie lepiej Jeśli zamiast tego użyłeś codecs.open() do automatycznego odkodowania zawartości:

import codecs 

sql = mdb.connect('localhost','admin','ugo&([email protected]','music_vibration', charset='utf8') 

with codecs.open('config/index/'+index, 'r', 'utf8') as findex: 
    for line in findex: 
     if u'#artiste' not in line: 
      continue 

     artiste=line.split(u'[:::]')[1].strip() 

    cursor = sql.cursor() 
    cursor.execute('SELECT COUNT(id) AS nbr FROM artistes WHERE nom=%s', (artiste,)) 
    if not cursor.fetchone()[0]: 
     cursor = sql.cursor() 
     cursor.execute('INSERT INTO artistes(nom,status,path) VALUES(%s, 99, %s)', (artiste, artiste + u'/')) 
     artists_inserted += 1 

Możesz odświeżyć Unicode i UTF-8 oraz kodowania. Mogę polecić następujące artykuły:

+0

Czy widzisz mój plz edycji? Jestem tak zagubiony ... – vekah

+4

@vekah: Czy postępowałeś zgodnie z instrukcjami zawartymi w [Pisanie ciągu znaków UTF-8 do MySQL z pythonem] (http://stackoverflow.com/q/6202726) –