python python-2.7

python - codificación de cadena y decodificación?



python-2.7 (4)

Aquí están mis intentos con mensajes de error. ¿Qué estoy haciendo mal?

string.decode("ascii", "ignore")

UnicodeEncodeError: ''ascii'' codec can''t encode character u''/xa0'' in position 37: ordinal not in range(128)

string.encode(''utf-8'', "ignore")

UnicodeDecodeError: ''ascii'' codec can''t decode byte 0xc2 in position 37: ordinal not in range(128)


Además de decode y encode revés, creo que parte de la respuesta aquí es, en realidad , no usar la codificación ascii . Probablemente no sea lo que quieres.

Para empezar, piense en str como si fuera un archivo de texto sin formato. Es solo un montón de bytes sin codificación realmente adjunta. Cómo se interpreta depende de la pieza de código que lo esté leyendo. Si no sabe de qué está hablando este párrafo, vaya a leer El mínimo absoluto de Joel, Todo desarrollador de software Absolutamente, Positivamente, debe saber sobre Unicode y conjuntos de caracteres en este momento, antes de ir más allá.

Naturalmente, todos somos conscientes del desastre que creó. La respuesta es, al menos dentro de la memoria, tener una codificación estándar para todas las cadenas. Ahí es donde entra el unicode . Tengo problemas para rastrear exactamente qué codificación utiliza internamente Python, pero en realidad no importa solo por esto. El punto es que usted sabe que es una secuencia de bytes que se interpretan de cierta manera. Entonces solo necesitas pensar en los personajes en sí, y no en los bytes.

El problema es que en la práctica, te encuentras con ambos. Algunas bibliotecas te dan un str , y algunos esperan un str . Ciertamente, eso tiene sentido siempre que esté transmitiendo una serie de bytes (por ejemplo, desde o hacia un disco o una solicitud web). Entonces, debes poder traducir de aquí para allá.

Ingrese codecs : es la biblioteca de traducción entre estos dos tipos de datos. Usas la encode para generar una secuencia de bytes ( str ) a partir de una cadena de texto ( unicode ) y usas la decode para obtener una cadena de texto ( unicode ) a partir de una secuencia de bytes ( str ).

Por ejemplo:

>>> s = "I look like a string, but I''m actually a sequence of bytes. /xe2/x9d/xa4" >>> codecs.decode(s, ''utf-8'') u"I look like a string, but I''m actually a sequence of bytes. /u2764"

¿Lo que pasó aquí? Le di a Python una secuencia de bytes, y luego le dije: "Dame la versión unicode de esto, dado que esta secuencia de bytes está en ''utf-8'' ". Hizo lo que le pedí, y esos bytes ( un carácter de corazón ) se tratan ahora como un todo, representado por su punto de código Unicode.

Vamos al revés:

>>> u = u"I''m a string! Really! /u2764" >>> codecs.encode(u, ''utf-8'') "I''m a string! Really! /xe2/x9d/xa4"

Le di a Python una cadena Unicode, y le pedí que tradujera la cadena en una secuencia de bytes usando la codificación ''utf-8'' . Lo hizo, y ahora el corazón es solo un montón de bytes que no puede imprimir como ASCII; entonces me muestra el hexadecimal.

Podemos trabajar con otras codificaciones, también, por supuesto:

>>> s = "I have a section /xa7" >>> codecs.decode(s, ''latin1'') u''I have a section /xa7'' >>> codecs.decode(s, ''latin1'')[-1] == u''/u00A7'' True >>> u = u"I have a section /u00a7" >>> u u''I have a section /xa7'' >>> codecs.encode(u, ''latin1'') ''I have a section /xa7''

( ''/xa7'' es el carácter de sección , tanto en Unicode como en Latin-1).

Entonces, para su pregunta, primero necesita averiguar en qué codificación se encuentra su str .

  • ¿Vino de un archivo? ¿De una solicitud web? De su base de datos? Entonces la fuente determina la codificación. Descubre la codificación de la fuente y úsala para convertirla en unicode .

    s = [get from external source] u = codecs.decode(s, ''utf-8'') # Replace utf-8 with the actual input encoding

  • O tal vez estás tratando de escribirlo en alguna parte. ¿Qué codificación espera el destino? Usa eso para traducirlo a str . UTF-8 es una buena opción para documentos de texto sin formato; la mayoría de las cosas pueden leerlo.

    u = u''My string'' s = codecs.encode(u, ''utf-8'') # Replace utf-8 with the actual output encoding [Write s out somewhere]

  • ¿Estás traduciendo hacia adelante y hacia atrás en memoria para la interoperabilidad o algo así? Luego solo elige una codificación y quédate con ella; ''utf-8'' es probablemente la mejor opción para eso:

    u = u''My string'' s = codecs.encode(u, ''utf-8'') newu = codecs.decode(s, ''utf-8'')

En la programación moderna, probablemente nunca desee utilizar la codificación ''ascii'' para nada de esto. Es un subconjunto extremadamente pequeño de todos los caracteres posibles, y ningún sistema que conozco lo usa por defecto ni nada.

Python 3 hace todo lo posible para que esto sea inmensamente claro simplemente cambiando los nombres. En Python 3, str fue reemplazado por bytes , y unicode fue reemplazado por str .


Adivinando todas las cosas omitidas de la pregunta original, pero, asumiendo Python 2.x, la clave es leer los mensajes de error cuidadosamente: en particular, donde llamas ''codificar'' pero el mensaje dice ''decodificar'' y viceversa, pero también el tipos de valores incluidos en los mensajes.

En el primer ejemplo, la string es de tipo unicode e intenta decodificarla, que es una operación que convierte una cadena de bytes a Unicode. Python intentó convertir el valor Unicode a str usando la codificación predeterminada ''ascii'', pero como la cadena contenía un carácter no ascii, se obtuvo el error que dice que Python no pudo codificar un valor Unicode . Aquí hay un ejemplo que muestra el tipo de cadena de entrada:

>>> u"/xa0".decode("ascii", "ignore") Traceback (most recent call last): File "<pyshell#7>", line 1, in <module> u"/xa0".decode("ascii", "ignore") UnicodeEncodeError: ''ascii'' codec can''t encode character u''/xa0'' in position 0: ordinal not in range(128)

En el segundo caso, haces el intento inverso de codificar una cadena de bytes. La codificación es una operación que convierte unicode en una cadena de bytes, por lo que Python intenta convertir la cadena de bytes a unicode primero y, como no le asignó una cadena de caracteres, falla el decodificador ascii predeterminado:

>>> "/xc2".encode("ascii", "ignore") Traceback (most recent call last): File "<pyshell#6>", line 1, in <module> "/xc2".encode("ascii", "ignore") UnicodeDecodeError: ''ascii'' codec can''t decode byte 0xc2 in position 0: ordinal not in range(128)


Esto se debe a que su cadena de entrada no se puede convertir de acuerdo con las reglas de codificación (estrictas de manera predeterminada).

No lo sé, pero siempre codifiqué usando directamente el constructor de Unicode (), al menos esa es la forma en la documentación oficial :

unicode(your_str, errors="ignore")


No puedes decodificar un unicode , y no puedes codificar un str . Intenta hacerlo al revés .