Pregunta

Comienzo con la creación de una variable de cadena con algunos no ascii utf-8 los datos codificados en ella:

>>> text = 'á'
>>> text
'\xc3\xa1'
>>> text.decode('utf-8')
u'\xe1'

El uso de unicode() en él plantea los errores...

>>> unicode(text)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: 
                    ordinal not in range(128)

...pero si sé que la codificación puedo usarlo como segundo parámetro:

>>> unicode(text, 'utf-8')
u'\xe1'
>>> unicode(text, 'utf-8') == text.decode('utf-8')
True

Ahora si tengo una clase que devuelve este texto en el __str__() método:

>>> class ReturnsEncoded(object):
...     def __str__(self):
...         return text
... 
>>> r = ReturnsEncoded()
>>> str(r)
'\xc3\xa1'

unicode(r) parece usar str() en ello, ya que genera el mismo error como unicode(text) arriba:

>>> unicode(r)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: 
                    ordinal not in range(128)

Hasta ahora todo está como estaba previsto!

Pero como nadie va a esperar, unicode(r, 'utf-8') ni siquiera se trate de:

>>> unicode(r, 'utf-8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: coercing to Unicode: need string or buffer, ReturnsEncoded found

Por qué?¿Por qué este comportamiento incoherente?Es un bug?es la intención?Muy torpe.

¿Fue útil?

Solución

El comportamiento parece confuso, pero intensional.Reproduzco aquí la totalidad de las unicode documentación de la En Python las Funciones Integradas De la documentación (para la versión 2.5.2, mientras escribo esto):

unicode([objeto[, codificación [errores]]])

De retorno de la cadena Unicode versión de objeto usando uno de los siguientes modos:

Si la codificación y/o errores que se dan, unicode() decodificar el objeto que puede ser una de 8 bits cadena o un búfer de caracteres utilizando el códec para la codificación.El parámetro de codificación es una cadena dar el nombre de una codificación;si la codificación no es conocido, LookupError es elevada.Manejo de errores se realiza de acuerdo a los errores;este especifica el tratamiento de los personajes que son no válido en la entrada de la codificación.Si el error es "estricta" (el valor predeterminado), una ValueError se eleva sobre los errores, mientras que un valor de "ignorar" causas de los errores para ser ignorado, y un valor de 'reemplazar' hace que el oficial de carácter Unicode de reemplazo, U+FFFD, para ser usado para reemplazar caracteres de entrada que no se puede decodificado.Véase también el códecs el módulo.

Si no hay parámetros opcionales son dadas, unicode() imitan la el comportamiento de str() excepto que devuelve cadenas Unicode en lugar de los 8 bits cadenas.Más precisamente, si el objeto es una Unicode cadena o subclase de la devolverá esa cadena Unicode sin cualquier adicional de decodificación aplicado.

Para los objetos que proporcionan un __unicode__() método, que llamaremos este método sin argumentos para crear una cadena Unicode.Para todos los demás objetos, de los 8 bits versión de la cadena o de la representación es solicitado, y luego se convierte a una cadena Unicode usando el codec para la codificación predeterminada en "estricta" de modo.

Nuevo en la versión 2.0.Cambiado en la versión 2.2:Apoyo para __unicode__() se añadió.

Así, cuando te llame unicode(r, 'utf-8'), y esto requiere de un 8-cadena de bits o un búfer de caracteres como el primer argumento, por lo que coacciona a su objeto con la __str__() el método, y los intentos para descifrar que el uso de la utf-8 códec.Sin el utf-8, el unicode() la función busca de un __unicode__() método en el objeto, y al no encontrarlo, se llama a la __str__() el método, como usted sugiere, tratando de usar el códec predeterminado para convertir a unicode.

Otros consejos

unicode no imagino la codificación del texto.Si el objeto puede imprimir a sí mismo como unicode, definir la __unicode__() método que devuelve una cadena Unicode.


El secreto es que unicode(r) no es en realidad, se llama __str__() sí.En su lugar, se busca un __unicode__() método.La implementación predeterminada de __unicode__() se llame __str__() y, a continuación, intentar decodificar el uso de la ascii conjunto de caracteres.Cuando se pasa de la codificación, unicode() se espera que el primer objeto a ser algo que puede ser decodificado -- es decir, una instancia de basestring.


El comportamiento es raro, porque se trata de decodificar como ascii si no me pasa 'utf-8'.Pero si me pasa 'utf-8' da un error diferente...

Eso es porque cuando se especifica "utf-8", que trata el primer parámetro es una cadena-como objeto para ser decodificados.Sin ella, trata el parámetro como un objeto a ser obligados a unicode.

No entiendo la confusión.Si usted sabe que el objeto de la text atributo siempre será codificado en UTF-8, basta con definir __unicode__() y entonces todo funcionará bien.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top