Bonjour.
Je travaille depuis une base MySql qui a de gros problèmes d'encodages. La base est déclaré en utf-8, mais les données à l'intérieur sont à 90% issu de données codés en windows-1252 passés tel quel en utf-8. 9% sont réellement de l'utf-8 et 1% sont du latin-1 (et je soupçonne qu'il y est encore d'autres encodages dans de rare cas...).
J'aimerais être averti quand une "erreur" est rencontré (quand je parle d'erreur, c'est un cas autre qu'un texte encodé en utf-8 qui présente des caractères windows-1252. Une string en utf-8 correctement encodé est une erreur...).
Pour me signaler l'erreur, j'utilise le module logging qui m'envoie un mail. Pour extraire les données dont j'ai besoin pour la suite de mon programme, j'utilise sqlalchemy.
Ce qui me pose problème, c'est de me signaler où se situe exactement l'erreur d'encodage, c'est à dire la table, la colonne et sous quelle référence. J'ai vraiment beaucoup de mal à comprendre (ou plutôt, à me mettre à la place de celui qui l'a écrit) la documentation de sqlalchemy.
Pour corriger les problèmes d'encodage et avoir du unicode "relativement" propre dans la suite du programme, j'hérite de TypeDecorator pour créer mon propre type sqlalchemy.
@add_logger est un décorator qui ajouter un objet logger à un autre objet.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 from sqlalchemy import types @add_logger class FakeUtf8String(types.TypeDecorator): """ La base de données est déclaré en utf-8, mais contient du windows-1252. Il faut donc passer par une étape intermédiaire, pour obtenir des strings unicodes qui puissent être exportable vers tout type d'encodages """ impl = types.String def process_result_value(self, value, dialect): """ Cette étape intervient juste après l'extraction des données dans la BDD, mais juste avant qu'il ne soit passé à l'objet python représentant cette base. """ if value: try: return value.encode('windows-1252').decode('windows-1252') except UnicodeError: self.logger.exception('Problème encodage sur ') return value # Commenter ou décommenter pour 'écraser' la classe String fourni avec SqlAlchemy String = FakeUtf8String
C'est un squelette, faut que j'écrive pour les autres types d'encodage, mais l'idée est là. Et comme vous pouvez le voir, je bloque sur self.logger.exception, où j'aimerai indiquer où se situe le problème. Je pense que je dois lever l'exception jusqu'à ce qu'elle remonte à l'objet contenant cette instance FakeUtf8String, qui contiendra certainement le nom de la colonne, mais je n'arrive pas à comprendre la doc de sqlalchemy...
Merci de m'avoir lu !
Partager