2008-11-06 7 views
15

J'écris un logiciel de traitement de courrier en Python qui rencontre des octets étranges dans les champs d'en-tête. Je soupçonne que c'est juste du courrier mal formé; le message lui-même prétend être nous-ascii, donc je ne pense pas qu'il y ait un vrai codage, mais je voudrais sortir une chaîne unicode approximant celle d'origine sans lancer un UnicodeDecodeError. Donc, je suis à la recherche d'une fonction qui prend un str et éventuellement quelques indices et fait de son mieux pour me redonner un unicode. Je pourrais en écrire un bien sûr, mais si une telle fonction existe, son auteur a probablement réfléchi un peu plus sur la meilleure façon d'y parvenir.Y at-il une fonction de bibliothèque Python qui tente de deviner le codage de caractères de certains octets?

Je sais aussi que la conception de Python préfère explicitement à implicite et que la bibliothèque standard est conçue pour éviter la magie implicite dans le décodage du texte. Je veux juste dire explicitement "allez-y et devinez".

Répondre

12

Pour autant que je sache, la bibliothèque standard n'a pas de fonction, bien qu'il ne soit pas trop difficile d'en écrire une comme suggéré ci-dessus. Je pense que la vraie chose que je cherchais était un moyen de décoder une chaîne et de garantir qu'elle ne déclencherait pas d'exception. Le paramètre errors de string.decode le fait.

def decode(s, encodings=('ascii', 'utf8', 'latin1')): 
    for encoding in encodings: 
     try: 
      return s.decode(encoding) 
     except UnicodeDecodeError: 
      pass 
    return s.decode('ascii', 'ignore') 
+1

Vous pouvez ignorer le cas '' ascii'' à la fin et utiliser simplement 'latin1', puisque' latin1' décodera toutes les valeurs de 256 octets sans erreur. –

20

Vous pouvez être intéressé par Universal Encoding Detector.

+0

+1 pour être 5 secondes plus rapide que moi :-) –

+0

Vraiment utile, merci. Mais pas dans la bibliothèque standard. – Nick

18

+1 pour le module chardet (proposé par @insin).

Il est pas dans la bibliothèque standard, mais vous pouvez facilement l'installer avec la commande suivante:

$ pip install chardet 

Example:

>>> import chardet 
>>> import urllib 
>>> detect = lambda url: chardet.detect(urllib.urlopen(url).read()) 
>>> detect('http://stackoverflow.com') 
{'confidence': 0.85663169917190185, 'encoding': 'ISO-8859-2'}  
>>> detect('https://stackoverflow.com/questions/269060/is-there-a-python-lib') 
{'confidence': 0.98999999999999999, 'encoding': 'utf-8'} 

Voir Installing Pip si vous ne possédez pas.

+1

Ne vous a-t-il pas semblé que 'ISO-8859-2' était un non-sens? –

+0

@John Machin: Oui, c'était le cas. Il est éducatif de montrer que vous ne devriez pas aveuglément lui faire confiance. Les résultats actuels sont différents ('utf-8' et 'ascii' en conséquence). – jfs

1

La meilleure façon de faire cela que j'ai trouvé est d'essayer de décoder de façon itérative un potentiel avec chacun des encodages les plus courants à l'intérieur d'un bloc try except.

Questions connexes