¿Existe una función de biblioteca de Python que intente adivinar la encoding de caracteres de algunos bytes?

Estoy escribiendo un software de procesamiento de correo en Python que se encuentra con bytes extraños en los campos de encabezado. Sospecho que esto es sólo un correo mal formado; el mensaje en sí dice ser nosotros-ascii, así que no creo que haya una verdadera encoding, pero me gustaría sacar una cadena Unicode que se aproxima a la original sin lanzar un UnicodeDecodeError .

Entonces, estoy buscando una función que tome un str y opcionalmente algunos consejos y haga todo lo posible para devolverme un unicode . Podría escribir una, por supuesto, pero si existe tal función, su autor probablemente haya pensado un poco más en la mejor manera de hacerlo.

También sé que el diseño de Python prefiere lo explícito a lo implícito y que la biblioteca estándar está diseñada para evitar la magia implícita en la deencoding del texto. Sólo quiero decir explícitamente “seguir adelante y adivinar”.

+1 para el módulo chardet (sugerido por @insin ).

No está en la biblioteca estándar, pero puede instalarlo fácilmente con el siguiente comando:

 $ pip install chardet 

Ejemplo :

 >>> 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'} 

Vea Instalar Pip si no tiene uno.

Usted puede estar interesado en Universal Detector de encoding .

Por lo que puedo decir, la biblioteca estándar no tiene una función, aunque no es demasiado difícil escribir una como se sugirió anteriormente. Creo que lo que estaba buscando era una forma de descodificar una cadena y garantizar que no lanzaría una excepción. El parámetro de errores de string.decode hace eso.

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

La mejor manera de hacer esto que he encontrado es tratar de descodificar iterativamente un prospecto con cada una de las codificaciones más comunes dentro de un bloque de prueba excepto.