Una de python: force_unicode

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.

Trackback URL

, , , ,

34 Comments on "Una de python: force_unicode"

  1. jesus
    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 :’(

  2. Pau Sanchez
    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.

  3. flea treatment
    30/11/2011 at 5:22 am Permalink

    You couldn’t be more precise.

Hi Stranger, leave a comment:

ALLOWED XHTML TAGS:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">

Subscribe to Comments