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.