Ya hemos conseguido que nuestra base de código que se ejecuta bajo Python 2.6. En el fin de prepararse para Python 3.0, hemos empezado a agregar:

de __futuro__ importación unicode_literals 

en nuestro .py archivos (como hemos modificarlas). Me pregunto si alguien ha estado haciendo esto y se ha ejecutado en cualquier no-evidentes errores (tal vez después de pasar un montón de tiempo de depuración).

6 Comentarios

  1. 101

    La principal fuente de problemas que yo he tenido trabajando con cadenas unicode es cuando se mezcla con codificación utf-8 cadenas unicode queridos.

    Por ejemplo, considere las siguientes secuencias de comandos.

    two.py

    # encoding: utf-8
    name = 'helló wörld from two'

    one.py

    # encoding: utf-8
    from __future__ import unicode_literals
    import two
    name = 'helló wörld from one'
    print name + two.name

    La salida de la ejecución de python one.py es:

    Traceback (most recent call last):
      File "one.py", line 5, in <module>
        print name + two.name
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 4: ordinal not in range(128)

    En este ejemplo, two.name es una codificación utf-8 de cadena (no unicode), ya que no importa unicode_literals, y one.name es una cadena unicode. Cuando la mezcla de ambos, python intenta decodificar la cadena codificada (asumiendo que es ascii) y convertir a unicode y falla. Funcionaría si usted hizo print name + two.name.decode('utf-8').

    Lo mismo puede suceder si usted codificar una cadena y tratar de mezcla de ellos más tarde.
    Por ejemplo, esto funciona:

    # encoding: utf-8
    html = '<html><body>helló wörld</body></html>'
    if isinstance(html, unicode):
        html = html.encode('utf-8')
    print 'DEBUG: %s' % html

    De salida:

    DEBUG: <html><body>helló wörld</body></html>

    Pero después de la adición de la import unicode_literals NO:

    # encoding: utf-8
    from __future__ import unicode_literals
    html = '<html><body>helló wörld</body></html>'
    if isinstance(html, unicode):
        html = html.encode('utf-8')
    print 'DEBUG: %s' % html

    De salida:

    Traceback (most recent call last):
      File "test.py", line 6, in <module>
        print 'DEBUG: %s' % html
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 16: ordinal not in range(128)

    Se produce un error porque 'DEBUG: %s' es una cadena unicode y por lo tanto de python intenta descodificar html. Un par de maneras para corregir la impresión están haciendo print str('DEBUG: %s') % html o print 'DEBUG: %s' % html.decode('utf-8').

    Espero que esto les ayude a entender los posibles errores al usar cadenas unicode.

    • Yo sugeriría ir con el decode() soluciones en lugar de los str() o encode() soluciones: la mayor frecuencia de uso de Unicode objetos, el más claro es el código, ya que lo que quieren es manipular cadenas de caracteres, no de las matrices de bytes con un externamente implícita de la codificación.
    • Por favor arreglar su terminología. when you mix utf-8 encoded strings with unicode ones UTF-8 Unicode y anen no 2 diferentes codificaciones Unicode es un estándar y UTF-8 es una de las codificaciones que se define.
    • Creo que se refiere a la mezcla de «codificado en utf-8 cadenas» objetos con unicode (de ahí decodificado) objetos. El primero es de tipo str, el último es el tipo de unicode. El ser diferente a los objetos, el problema puede surgir si intenta suma/concatenar/interpolan
    • Aplica esto a python>=2.6 o python==2.6?
  2. 16

    También en 2.6 (antes de python 2.6.5 RC1+) unicode literales no juega bien con los parámetros de palabra clave (issue4978):

    El siguiente código, por ejemplo, funciona sin unicode_literals, pero no con TypeError: keywords must be string si unicode_literals se utiliza.

      >>> def foo(a=None): pass
      ...
      >>> foo(**{'a':1})
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
          TypeError: foo() keywords must be strings
    • Sólo para tu INFORMACIÓN, python 2.6.5 RC1+ ha arreglado esto.
  3. 13

    Me di cuenta que si añades el unicode_literals directiva también debe agregar algo como:

     # -*- coding: utf-8

    a la primera o segunda línea .py archivo. De lo contrario, las líneas tales como:

     foo = "barré"

    resultar en un error, tales como:

    SyntaxError: No-ASCII carácter '\xc3' en el archivo mumble.py en la línea 198, 
    pero sin ningún tipo de codificación declarado; ver http://www.python.org/peps/pep-0263.html 
    para más detalles 
    
    • +1. Aunque no deberíamos hacer esto en todo de las circunstancias?
    • Python 3 se supone que los archivos se UTF8 por defecto
    • Pero Python 2 no, y le dará el error de sintaxis si no utilice caracteres ascii incluso en los comentarios! Así que en mi humilde opinión # -*- coding: utf-8 es prácticamente una declaración obligatoria, independientemente de si usted utiliza unicode_literals o no
    • El -*- no es necesario; si usted se va para el emacs-compatible manera, creo que iba a necesitar -*- encoding: utf-8 -*- (véase el -*- al final también). Todo lo que necesitas es coding: utf-8 (o incluso = en lugar de : ).
    • Recibe este error o si no te from __future__ import unicode_literals.
    • Emacs compatibilidad requiere # -*- coding: utf-8 -*- con la «codificación» (no «codificación» o «fileencoding» o cualquier otra cosa – Python sólo busca «codificación», independientemente de cualquier prefijo).

  4. 7

    También tomar en cuenta que unicode_literal afectará eval() pero no repr() (una relación asimétrica de comportamiento que en mi humilde opinión es un error), es decir, eval(repr(b'\xa4')) no será igual a b'\xa4' (como lo sería con Python 3).

    Idealmente, el código siguiente sería un invariante, que debería funcionar siempre, para todas las combinaciones de unicode_literals y Python {2.7, 3.x} de uso:

    from __future__ import unicode_literals
    
    bstr = b'\xa4'
    assert eval(repr(bstr)) == bstr # fails in Python 2.7, holds in 3.1+
    
    ustr = '\xa4'
    assert eval(repr(ustr)) == ustr # holds in Python 2.7 and 3.1+

    La segunda afirmación que sucede a trabajar, ya que repr('\xa4') evalúa a u'\xa4' en Python 2.7.

    • Me siento como el problema más grande aquí es que usted está usando repr para regenerar un objeto. El repr documentación dice claramente que este es no un requisito. En mi opinión, esto relega a repr para algo útil para la depuración.
  5. 5

    Hay más.

    Hay bibliotecas y builtins que esperar cadenas que no toleran unicode.

    Dos ejemplos:

    builtin:

    myenum = type('Enum', (), enum)

    (ligeramente esotic) no funciona con unicode_literals: tipo() espera una cadena.

    biblioteca:

    from wx.lib.pubsub import pub
    pub.sendMessage("LOG MESSAGE", msg="no go for unicode literals")

    no funciona: el wx pubsub biblioteca espera una cadena de tipo de mensaje.

    El primero es esotérico y fija fácilmente con

    myenum = type(b'Enum', (), enum)

    pero el último es devastador si el código está lleno de llamadas de la pub.sendMessage() (que la mía es).

    Dang, eh?!?

    • Y el tipo de cosas también se filtra en metaclasses – por lo que en Django cualquier cadenas de declarar en class Meta: debe ser b'field_name'
    • Sí … en mi caso me di cuenta de que valió la pena el esfuerzo de buscar y reemplazar todos los sendMessage cadenas con b’ versiones. Si usted quiere evitar el temido «decode» de excepción, no hay nada como estrictamente el uso de unicode en su programa, la conversión en de entrada y de salida según sea necesario (el «unicode sandwich» mencionado en algunas papel que he leído sobre el tema). En general, unicode_literals ha sido una gran victoria para mí…

Dejar respuesta

Please enter your comment!
Please enter your name here