utf8 u00f3 open escape python unicode python-2.6 unicode-literals

u00f3 - unicode escape python



¿Algún problema con unicode_literals en Python 2.6? (5)

Encontré que si agrega la directiva unicode_literals también debería agregar algo como:

# -*- coding: utf-8

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

foo = "barré"

provocar un error como:

SyntaxError: Non-ASCII character ''/xc3'' in file mumble.py on line 198, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details

Ya hemos conseguido que nuestra base de código se ejecute en Python 2.6. Para prepararnos para Python 3.0, hemos comenzado a agregar:

from __future__ import unicode_literals

en nuestros archivos .py (a medida que los modifiquemos). Me pregunto si alguien más ha estado haciendo esto y se ha encontrado con problemas no obvios (tal vez después de pasar mucho tiempo depurando).


Hay mas.

Hay bibliotecas y edificios que esperan cadenas que no toleren unicode.

Dos ejemplos:

incorporado:

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

(ligeramente erótico) no funciona con unicode_literals: type () espera una cadena.

biblioteca:

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

no funciona: la biblioteca wx pubsub espera un tipo de mensaje de cadena.

El primero es esotérico y se soluciona fácilmente con

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

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

Dang it, eh?!?


La principal fuente de problemas que he tenido al trabajar con cadenas de caracteres unicode es cuando se mezclan cadenas codificadas en utf-8 con unidades Unicode.

Por ejemplo, considere los siguientes scripts.

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

El resultado de ejecutar 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 cadena codificada en utf-8 (no unicode) ya que no unicode_literals , y one.name es una cadena unicode. Cuando mezcla ambos, Python intenta decodificar la cadena codificada (asumiendo que es ascii) y la convierte a unicode y falla. Funcionaría si print name + two.name.decode(''utf-8'') .

Lo mismo puede suceder si codifica una cadena e intenta mezclarlas 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

Salida:

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

Pero después de agregar 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

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)

No funciona porque ''DEBUG: %s'' es una cadena unicode y, por lo tanto, python intenta decodificar html . Algunas formas de corregir la impresión son print str(''DEBUG: %s'') % html o print ''DEBUG: %s'' % html.decode(''utf-8'') .

Espero que esto te ayude a comprender los posibles errores al usar cadenas de caracteres unicode.


También en 2.6 (antes de Python 2.6.5 RC1 +) literales unicode no se juega bien con argumentos de palabra clave ( issue4978 ):

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

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


También tenga en cuenta que unicode_literal afectará a eval() pero no a repr() (un comportamiento asimétrico que imho es un error), es decir, eval(repr(b''/xa4'')) no será igual a b''/xa4'' (como lo haría con Python 3).

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

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 funciona, ya que repr(''/xa4'') evalúa como u''/xa4'' en Python 2.7.