web-dev-qa-db-fra.com

python codant en utf-8

Je fais des scripts en python. Je crée une chaîne que je sauvegarde dans un fichier. Cette chaîne contient beaucoup de données, provenant de l'arborescence et des noms de fichiers d'un répertoire. Selon convmv, toute mon arborescence est en UTF-8.

Je veux tout garder en UTF-8 car je vais le sauvegarder dans MySQL après. Pour l'instant, dans MySQL, qui est en UTF-8, des problèmes surviennent (par exemple, é ou è - I'am français).

Je veux que python utilise toujours la chaîne en tant que UTF-8. J'ai lu des informations sur Internet et j'ai fait comme ça.

Mon script commence par ceci:

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

Et quand j'exécute, voici la réponse: UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 2171: ordinal not in range(128)

Edit: Je vois, dans mon fichier, les accents sont bien écrits. Après avoir créé ce fichier, je le lis et je l’écris dans MySQL. Mais je ne comprends pas pourquoi, mais j'ai eu un problème avec l'encodage. Ma base de données MySQL est dans utf8 ou semble être une requête SQL SHOW variables LIKE 'char%' ne me renvoie que utf8 ou binary.

Ma fonction ressemble à ceci:

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

Et l'artiste qui est bien affiché dans le fichier écrit mal dans le BDD. Quel est le problème ?

42
vekah

Vous n'avez pas besoin d'encoder des données déjà encodées . Lorsque vous essayez de faire cela, Python essayera d'abord de le décoder en unicode avant de pouvoir le recoder. à UTF-8. C'est ce qui manque ici:

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

Il suffit d'écrire vos données directement dans le fichier, il n'y a aucun besoin d'encoder des données déjà encodées.

Si vous construisez plutôt les valeurs unicode, vous devrez en effet coder celles-ci pour pouvoir les écrire dans un fichier. Vous voudriez utiliser codecs.open() à la place, ce qui retourne un objet fichier qui encodera les valeurs unicode en UTF-8 pour vous.

Vous aussi vraiment ne voulez pas écrire la nomenclature UTF-8, sauf si vous devez pour prendre en charge les outils Microsoft qui ne peuvent pas lire UTF-8 autrement (tels que MS Notepad).

Pour votre problème d'insertion MySQL, vous devez faire deux choses:

  • Ajoutez charset='utf8' à votre appel MySQLdb.connect().

  • Utilisez unicode objets, et non pas str objets lors de l'interrogation ou de l'insertion, mais utilisez des paramètres SQL afin que le connecteur MySQL puisse faire le bon choix. chose pour vous:

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

Cela fonctionnera peut-être mieux si vous utilisiez codecs.open() pour décoder le contenu automatiquement:

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

Vous voudrez peut-être mettre à jour les codages Unicode et UTF-8. Je peux recommander les articles suivants:

54
Martijn Pieters

Malheureusement, la méthode string.encode () n'est pas toujours fiable. Consultez ce fil pour plus d'informations: Quel est le moyen le plus sûr de convertir une chaîne (utf-8 ou autre) en une simple chaîne ASCII en python

3
Ev Haus