La principal fuente de problemas que he tenido al trabajar con cadenas Unicode es cuando se mezclan cadenas codificadas en utf-8 con cadenas 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 correr 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 se importó unicode_literals
, y one.name
es una cadena unicode. Cuando mezcla ambos, Python intenta decodificar la cadena codificada (asumiendo que es ascii) y convertirla a Unicode y falla. Funcionaría si lo hicieras print name + two.name.decode('utf-8')
.
Lo mismo puede suceder si codifica una cadena e intenta mezclarlos 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 el 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)
Falla porque 'DEBUG: %s'
es una cadena Unicode y, por lo tanto, Python intenta decodificar html
. Un par de formas de arreglar la impresión son haciendo print str('DEBUG: %s') % html
o print 'DEBUG: %s' % html.decode('utf-8')
.
Espero que esto le ayude a comprender las posibles trampas al usar cadenas Unicode.
decode()
soluciones en lugar de las solucionesstr()
oencode()
: cuanto más a menudo use objetos Unicode, más claro será el código, ya que lo que desea es manipular cadenas de caracteres, no matrices de bytes con una codificación implícita externamente.