Pertanyaan python encoding utf-8


Saya melakukan beberapa skrip dengan python. Saya membuat string yang saya simpan dalam file. String ini mendapat banyak data, berasal dari arborescence dan nama file dari sebuah direktori. Menurut convmv, semua arborescence saya ada di UTF-8.

Saya ingin menyimpan semuanya di UTF-8 karena saya akan menyimpannya di MySQL setelahnya. Untuk saat ini, di MySQL, yang ada di UTF-8, saya mendapat masalah dengan beberapa karakter (seperti é atau è - I'am French).

Saya ingin python selalu menggunakan string sebagai UTF-8. Saya membaca beberapa informasi di internet dan saya suka ini.

Naskah saya dimulai dengan ini:

 #!/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!

Dan ketika saya mengeksekusi, inilah jawabannya: UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 2171: ordinal not in range(128)

Edit: Saya melihat, dalam file saya, aksen ditulis dengan baik. Setelah membuat file ini, saya membacanya dan saya menuliskannya ke MySQL. Tapi saya tidak mengerti mengapa, tapi saya punya masalah dengan encoding. Database MySQL saya di utf8, atau tampaknya query SQL SHOW variables LIKE 'char%' mengembalikan saya hanya utf8 atau biner.

Fungsi saya terlihat seperti ini:

#!/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')

Dan artis yang ditampilkan dengan baik di dalam file menulis buruk ke dalam BDD. Apa masalahnya ?


36
2018-02-26 15:06


asal


Jawaban:


Anda tidak perlu menyandikan data apa adanya sudah dikodekan. Ketika Anda mencoba untuk melakukan itu, Python pertama akan mencoba membaca sandi untuk unicode sebelum dapat mengkodekan kembali ke UTF-8. Itulah yang gagal di sini:

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

Tulis saja data Anda langsung ke file, ada tidak perlu menyandikan data yang sudah dikodekan.

Jika Anda malah membangun unicode nilai sebagai gantinya, Anda memang harus menyandikannya agar bisa ditulis ke file. Anda ingin menggunakannya codecs.open() sebaliknya, yang mengembalikan objek file yang akan menyandikan nilai unicode ke UTF-8 untuk Anda.

Kamu juga sangat tidak ingin menulis UTF-8 BOM, kecuali kalau kamu memiliki untuk mendukung alat Microsoft yang tidak dapat membaca UTF-8 sebaliknya (seperti MS Notepad).

Untuk masalah masukkan MySQL Anda, Anda perlu melakukan dua hal:

  • Menambahkan charset='utf8' untuk Anda MySQLdb.connect() panggilan.

  • Menggunakan unicode benda, bukan str objek saat bertanya atau memasukkan, tetapi menggunakan parameter sql sehingga konektor MySQL dapat melakukan hal yang benar untuk Anda:

    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'/'))
    

Ini mungkin benar-benar bekerja lebih baik jika Anda menggunakannya codecs.open() untuk memecahkan kode konten secara otomatis sebagai gantinya:

import codecs

sql = mdb.connect('localhost','admin','ugo&(-@F','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

Anda mungkin ingin memoles Unicode dan UTF-8 dan encodings. Saya dapat merekomendasikan artikel berikut:


48
2018-02-26 15:10



Sayangnya, metode string.encode () tidak selalu dapat diandalkan. Lihat utas ini untuk informasi lebih lanjut: Apa cara yang sangat mudah untuk mengonversi beberapa string (utf-8 atau yang lain) menjadi string ASCII sederhana dengan python


3
2018-02-03 16:50