Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
724 connectés 

  FORUM HardWare.fr
  Programmation
  Python

  [Python]Les accents contre-attaquent (sur mysql)

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[Python]Les accents contre-attaquent (sur mysql)

n°1799126
Shadew
Posté le 13-10-2008 à 10:05:11  profilanswer
 

Kikoo,
 
Python et les acents c'est la folie!! J'essaie de transférer des données depuis un fichier XML vers une BDD mysql avec MysqlDB, mais ça foire. Voici le code:

Code :
  1. for member in root:
  2. querystr ="INSERT INTO member VALUES ('%s','%s','%s');"%(unicode(u'%s'%member[0].text),unicode(u'%s'%member[1].text),member[2].text)
  3. print querystr
  4. conn.query(querystr.encode('ISO-8859-1'))
  5. conn.commit()


 
Avec cette version, les accents contenu dans querystr s'affiche bien avec le print mais ils deviennent des thêta grec dans ma BDD. Je pense que c'est dû à l'encode(iso), j'ai donc virer l'encode:
 

Code :
  1. for member in root:
  2. querystr ="INSERT INTO member VALUES ('%s','%s','%s');"%(unicode(u'%s'%member[0].text),unicode(u'%s'%member[1].text),member[2].text)
  3. print querystr
  4. conn.query(querystr)
  5. conn.commit()


 
Avec cette version du code, les accents contenu dans querystr s'affiche toujours bien avec le print mais j'ai alors une erreur:

Code :
  1. Traceback (most recent call last):
  2.   File "profils.py", line 44, in <module>
  3.     conn.query(querystr.decode(fichierEncodXML))
  4. UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 40:
  5. ordinal not in range(128)


 
Donc si j'encode pas il me met un thêta et si j'encode pas (ou que je decode), il me met une erreur de codec.
 
Quelqu'un pourrait-il m'aider svp?
 
P.S.: j'utilise les query/commit plutôt que les execute du cursor car ces derniers n'enregistraient pas les données dans ma BDD
 

mood
Publicité
Posté le 13-10-2008 à 10:05:11  profilanswer
 

n°1799448
masklinn
í dag viðrar vel til loftárása
Posté le 13-10-2008 à 15:26:06  profilanswer
 

1.

Code :
  1. unicode(u'%s'%member[0].text),unicode(u'%s'%member[1].text)


c'est du grand n'importe quoi
2. "j'utilise les query/commit plutôt que les execute du cursor car ces derniers n'enregistraient pas les données dans ma BDD" t'as essayé de commit() après execute/executemany?
3. Spécifie un charset dans MySQLdb.open, sinon tu vas soit avoir une erreur d'encoding (cas 2, mysqldb tente d'encoder en ascii par défaut je présume) soit directement des données binaires/mal encodées en DB (cas 1)

 

Cf doc mysqldb http://mysql-python.sourceforge.net/MySQLdb.html

Message cité 1 fois
Message édité par masklinn le 13-10-2008 à 15:27:56

---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
n°1799517
Shadew
Posté le 13-10-2008 à 16:35:55  profilanswer
 

masklinn a écrit :

1.

Code :
  1. unicode(u'%s'%member[0].text),unicode(u'%s'%member[1].text)


c'est du grand n'importe quoi
2. "j'utilise les query/commit plutôt que les execute du cursor car ces derniers n'enregistraient pas les données dans ma BDD" t'as essayé de commit() après execute/executemany?
3. Spécifie un charset dans MySQLdb.open, sinon tu vas soit avoir une erreur d'encoding (cas 2, mysqldb tente d'encoder en ascii par défaut je présume) soit directement des données binaires/mal encodées en DB (cas 1)

 

Cf doc mysqldb http://mysql-python.sourceforge.net/MySQLdb.html

 

2. J'avais essayé mais le cursor n'a pas de membre de membre commit(), par contre je viens de penser que je pouvais toujours commiter la connexion, ce que je viens de faire et ça fonctionne  :D

 

Grâce à tes remarques, j'ai modif pendant 30 minutes et suite à divers modif, je suis arrivé à ça:

Code :
  1. conn = MySQLdb.connect(host,user,passwd,dbName)
  2. cursor = conn.cursor()
  3. cursor.execute("""CREATE TABLE member(pseudo CHAR(50) NOT NULL, classe CHAR (50) NOT NULL , dateInscr DATETIME, PRIMARY KEY(pseudo));""" )
  4. conn.commit()
  5. for member in root:
  6.    querystr =u"INSERT INTO member VALUES ('%s','%s','%s');"%(member[0].text,member[1].text,member[2].text)
  7.    print querystr
  8.    cursor.execute(querystr.encode(sys.stdout.encoding))
  9.    conn.commit()
 

Qui marche très bien  :)

 

Merci beaucoup!!!

Message cité 1 fois
Message édité par Shadew le 13-10-2008 à 16:36:30
n°1799549
masklinn
í dag viðrar vel til loftárása
Posté le 13-10-2008 à 16:59:45  profilanswer
 

Shadew a écrit :

Qui marche très bien  :)


Non, ça marche pas du tout
Pour commencer, où est la spécification de charset que j'ai demandé? elle est à faire dans MySQLdb.connect, tu n'as pas à encoder manuellement quoi que ce soit.
 
Secundo,

Shadew a écrit :

Code :
  1. querystr =u"INSERT INTO member VALUES ('%s','%s','%s');"%(member[0].text,member[1].text,member[2].text)



c'est dangereux. Si un de tes objets contient un caractère (') tout pête, et si jamais ce sont des données qui viennent d'utilisateurs quelconques ils peuvent faire ce qu'ils veulent avec ta db, l'intérêt d'utiliser cursor.execute c'est justement qu'il prépare tes requêtes pour qu'elles soient tout le temps propres sans ce genre de trucs
 
La version correcte, c'est:

Code :
  1. querystr = u"INSERT INTO member VALUES ('%s','%s','%s');"
  2. cursor.execute(querystr, (member[0].text,member[1].text,member[2].text))


là mysqldb va se charger de tout rendre propre (note: pas besoin de créer querystr ici, sauf pour le logger).
 
Tertio, plutôt que d'itérer manuellement et de commiter après chaque insert, je suggérerais d'utiliser executemany et de transformer tes données d'entrée en quelque chose qu'il peut consommer, avec une list comprehension par exemple:

Code :
  1. querystr =u"INSERT INTO member VALUES ('%s','%s','%s');"
  2. data = [(member0.text, member1.text, member2.text) for member0, member1, member2 in root]
  3. cursor.executemany(querystr, data)
  4. con.commit()


(note: idem, pas besoin de créer data, tu peux générer tes données directement dans executemany
De cette manière, ton code est plus clair, tu as une seule transaction, il n'y a pas d'itération manuelle et si mysqldb implémente un batch insert (chose dont je n'ai aucune idée) ça lui permet de l'utiliser.
(note finale: je suis sûr que tu peux trouver de meilleurs noms que "member0", "member1" et "member2" histoire de rendre leur rôle clair)


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
n°1799761
Shadew
Posté le 13-10-2008 à 23:31:09  profilanswer
 

Voilà, j'ai adapté avec le executemany. J'ai encore des problèmes à l'encodage. Voici le code actuel:

Code :
  1. conn = MySQLdb.connect(host,user,passwd,dbName,charset=sys.stdout.encoding)
  2. cursor = conn.cursor()
  3. cursor.execute("""CREATE TABLE member(pseudo CHAR(50) NOT NULL, classe CHAR (50) NOT NULL , dateInscr DATETIME, PRIMARY KEY(pseudo));""" )
  4. querystr =u"INSERT INTO member VALUES (%s,%s,%s);"
  5. data = [(pseudo.text, classe.text, dateInscr.text) for pseudo, classe, dateInscr in root]
  6. cursor.executemany(querystr, data)
  7. conn.commit()


 
Et là j'ai droit à l'erreur :

Code :
  1. _mysql_exceptions.OperationalError: (2019, "Can't initialize character set cp437
  2. (path: C:\\mysql\\\\share\\charsets\\)" )


 
Donc apparement, il ne supporte pas, lors de la connexion, l'encodage nécessaire pour pouvoir encoder sans accents (le cp437). Limite je pourrais l'ouvrir en latin1 (ça il supporte, il supporte pas non plus l'ISO) et décoder la chaine pour la ré-encoder en latin1 mais c'est bourrin et ça revient à encoder manuellement (donc on revient au point de départ).J'ai aussi essayer le use_unicode = True, mais là encore mes accents ne passent pas (je me retrouve avec des thêta dans la BDD). J'ai essayé un autre truc et ça ça marche:  

Code :
  1. conn = MySQLdb.connect(host,user,passwd,dbName)
  2. cursor = conn.cursor()
  3. cursor.execute("""CREATE TABLE member(pseudo CHAR(50) NOT NULL, classe CHAR (50) NOT NULL , dateInscr DATETIME, PRIMARY KEY(pseudo));""" )
  4. querystr =u"INSERT INTO member VALUES (%s,%s,%s);"
  5. data = [(pseudo.text.encode(sys.stdout.encoding), classe.text.encode(sys.stdout.encoding), dateInscr.text.encode(sys.stdout.encoding)) for pseudo, classe, dateInscr in root]
  6. cursor.executemany(querystr, data)
  7. conn.commit()


Donc je ré-encode les éléments à ajouter dans la base de données.  
 
Le problème quand je fais ça c'est que tu m'as dit que

Citation :

tu n'as pas à encoder manuellement quoi que ce soit

Il y a une raison de portabilité ou de sécurité à cela?
 
En tout cas merci pour ton aide, j'avais complétement oublier que le ' pouvait tout faire foirer et c'est écrit bien plus proprement comme ça!!
 
P.S.: tout à l'heure, j'avais déjà essayé le charset mais ça ne marchait pas mieux que maintenant, c'est pour ça que je m'était contenté de les encoder manuellement.


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  Python

  [Python]Les accents contre-attaquent (sur mysql)

 

Sujets relatifs
erreur de requete??MySQL server version for the right syntax to use ne[Python]Parser un fichier XML contenant des accents
prog en pythonCherche programmeur python gtk2, glade2, open source
utiliser des accents dans les noms de variables ?xampp windows 2000 serveur mysql php5
[MySQL] trouver la derniére modification !turtle python et les math/geometrie : dur dur...
Plus de sujets relatifs à : [Python]Les accents contre-attaquent (sur mysql)


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR