\0_ Lire un fichier en Python sans risquer l'UnicodeDecodeError

mardi 02 mars 2010

Chez mon client préféré, j'ai écrit un petit script en python pour bidouiller des fichiers. En gros, le script lit des fichiers et répartit leur contenu dans d'autres fichiers. Le script tournait à merveille, lancé par le très utile pycron, qui remplace avantageusement le planificateur de tâches de Windows (la différence majeure étant que pycron, lui, fonctionne), et tout allait pour le mieux dans le meilleur des mondes.

Après quelques semaines, le script ne fonctionnait plus. "Damned !" m'écriais-je alors que je constatais avec déception l'absence de log. Une petite intervention plus tard, nous voilà en possession du message d'erreur :
Traceback (most recent call last):
  File "C:\Scripts\UpdateArchives\updateArchives.py", line 12, in <module>
    for line in f:
  File "C:\Python31\lib\encodings\cp1252.py", line 23, in decode
    return codecs.charmap_decode(input,self.errors,decoding_table)[0]
UnicodeDecodeError: 'charmap' codec can't decode byte 0x90 in position 21: character maps to <undefined>

Dans le for line in f: où se produit l'erreur, f est un fichier précédemment ouvert. J'ai donc identifié le fichier défectueux et, vérification faite dans plusieurs éditeurs de texte, constaté qu'effectivement, il y avait bien un caractère foireux dedans.
La solution, qui n'était pas vraiment facile facile à dénicher, consiste à ouvrir le fichier en spécifiant errors='ignore', indiquant par là au convertisseur de caractères que c'est pas la peine de brailler comme une chèvre et d'alerter tout le village quand il rencontre un caractère qu'il n'arrive pas à traduire, et qu'il n'a qu'à faire comme s'il ne l'avait pas vu.
Attention, le caractère n'est pas remplacé par un carré ou un point d'interrogation, il disparait complètement. Ce comportement me convenait, mais ça ne sera peut-être pas votre cas.

Au final, l'ouverture de fichier devient :
f = open(filename, "r", errors='ignore')

Au passage, je note que la doc de python est un peu bordélique : dans la section sur la fonction intrinsèque open, aucune mention n'est faite du paramètre errors. En revanche, la doc de codecs.open indique son existence, mais sans en préciser les valeurs possibles >_< Pour les connaitre, il faut lire la doc de codecs.register. Logique.

Si vous voulez observer le problème chez vous, j'ai écrit un script qui le reproduit.

Réagir :






(ne sera pas affiché - gravatar)
(si vous ne le connaissez pas, voir cette page)
(mais qu'est-ce que c'est ? - télécharger)



  • Pour faire du gras gras : <b>gras</b>
  • Pour faire de l'italique : <i>italique</i>
  • Pour souligner : <u>souligné</u>
  • Pour barrer : <s>barré</s>
  • Pour faire un citation : <blockquote>citation</blockquote>
  • Pour faire un lien : <a href="adresse du lien">texte du lien</a>
  • Pour mettre une image : <img src="adresse de l'image"/>
  • nop se gratte l'oreille : /me se gratte l'oreille