Las codificaciones de caracteres (character encoding) son la mayor patraña jamás inventada, gracias a dios se inventó Unicode, con sus variantes UTF-8 y UTF-32.
Para mi, UTF-8 es, y debería ser el estándar para guardar o enviar cadenas de texto.
Los lenguajes de programación, python incluido, no deberían soportar otra cosa que no fuera UTF-8 o cadenas de bytes. La verdad es que lo voy a dejar aquí, porque cada vez que pienso en este tema, me enciendo.
El caso es que el soporte de codificaciones de texto en Python me parece lo peor. ¿Por qué? Porque no es suficientemente inteligente para mezclar cosas, y lanza excepciones a la mínima.
Hasta hoy, usaba str.decode(‘utf-8′, ‘ignore’) donde str es la cadena que quiero convertir a UTF-8, pero ni siquiera esto me libraba de excepciones.
Hoy, buscando otra vez una solución, he encontrado la función force_unicode del frámework django. De momento, con las pruebas que he hecho, se lo come todo. Es perfecto.
Símplemente quería compartir esto:
def force_unicode(s, encoding='utf-8', errors='ignore'): """ Returns a unicode object representing 's'. Treats bytestrings using the 'encoding' codec. """ import codecs if s is None: return '' try: if not isinstance(s, basestring,): if hasattr(s, '__unicode__'): s = unicode(s) else: try: s = unicode(str(s), encoding, errors) except UnicodeEncodeError: if not isinstance(s, Exception): raise # If we get to here, the caller has passed in an Exception # subclass populated with non-ASCII data without special # handling to display as a string. We need to handle this # without raising a further exception. We do an # approximation to what the Exception's standard str() # output should be. s = ' '.join([force_unicode(arg, encoding, errors) for arg in s]) elif not isinstance(s, unicode): # Note: We use .decode() here, instead of unicode(s, encoding, # errors), so that if s is a SafeString, it ends up being a # SafeUnicode at the end. s = s.decode(encoding, errors) except UnicodeDecodeError, e: if not isinstance(s, Exception): raise UnicodeDecodeError (s, *e.args) else: # If we get to here, the caller has passed in an Exception # subclass populated with non-ASCII bytestring data without a # working unicode method. Try to handle this without raising a # further exception by individually forcing the exception args # to unicode. s = ' '.join([force_unicode(arg, encoding, errors) for arg in s]) return s
Estoy convencido de que si tienes problemas con los strings en python, sabrás apreciar este código.
English
30/08/2010 at 1:45 pm Permalink
Hola, me arroja este error :S
.... in force_unicode if not isinstance(s, basestring,):
NameError: global name 'basestring' is not defined
Antes de probar el codigo que has aportado estaba intentando hacer:
alianza = linea[pos_ini+2 : pos_fin].decode("utf-8")
Esperaba que recogiera bien las excepciones, por que parece que el ignore con python 3 no hay manera
Lo mas normal sea que no haya incluido algo, pero al parece es que en python 3 el tema de las cadenas ha cambiado un poco:
http://docs.python.org/release/3.0.1/whatsnew/3.0.html#text-vs-data-instead-of-unicode-vs-8-bit
Pero no me manejo con el ingles yo :’(
02/09/2010 at 2:22 am Permalink
El código de arriba está pensado para Python 2.5 / 2.6, la verdad es que en Python 3.0 esperaba que nada de esto hiciese falta, en teoria todo debería ser unicode.
30/11/2011 at 5:22 am Permalink
You couldn’t be more precise.