¿Cuál es la diferencia entre codificar / decodificar?

180

Nunca he estado seguro de entender la diferencia entre decodificación y codificación str / unicode.

Sé que str().decode()es para cuando tienes una cadena de bytes que sabes que tiene una cierta codificación de caracteres, dado que el nombre de codificación devolverá una cadena unicode.

Sé que unicode().encode()convierte caracteres unicode en una cadena de bytes de acuerdo con un nombre de codificación dado.

Pero no entiendo para qué str().encode()y unicode().decode()para qué . ¿Alguien puede explicar, y posiblemente también corregir cualquier otra cosa que me haya equivocado anteriormente?

EDITAR:

Varias respuestas dan información sobre lo que .encodehace en una cadena, pero nadie parece saber qué .decodehace para Unicode.

ʞɔıu
fuente
Creo que la segunda respuesta de esta página es lo suficientemente clara y concisa.
Ben

Respuestas:

106

El decodemétodo de cadenas unicode realmente no tiene ninguna aplicación (a menos que tenga algunos datos que no sean de texto en una cadena unicode por alguna razón, consulte a continuación). Está principalmente allí por razones históricas, creo. En Python 3 se ha ido por completo.

unicode().decode()realizará una codificación implícita de susar el códec predeterminado (ascii). Verifique esto así:

>>> s = u'ö'
>>> s.decode()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf6' in position 0:
ordinal not in range(128)

>>> s.encode('ascii')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf6' in position 0:
ordinal not in range(128)

Los mensajes de error son exactamente iguales.

Porque str().encode()es al revés: intenta una decodificación implícita de sla codificación predeterminada:

>>> s = 'ö'
>>> s.decode('utf-8')
u'\xf6'
>>> s.encode()
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)

Usado así, str().encode()también es superfluo.

Pero hay otra aplicación del último método que es útil: hay codificaciones que no tienen nada que ver con los conjuntos de caracteres y, por lo tanto, se pueden aplicar a cadenas de 8 bits de manera significativa:

>>> s.encode('zip')
'x\x9c;\xbc\r\x00\x02>\x01z'

Sin embargo, tiene razón: el uso ambiguo de la "codificación" para ambas aplicaciones es ... extraño. Una vez más, con los tipos separados bytey stringen Python 3, esto ya no es un problema.


fuente
44
.decode()en cadenas Unicode podría ser útil, por ejemplo,print u'\\u0203'.decode('unicode-escape')
jfs
Buen ejemplo @JFSebastian en python3, supongo que lo harías:print u'\\u0203'.encode('utf8').decode('unicode-escape')
AJP
1
@AJP: en Python 3:codecs.decode(u'\\u0203', 'unicode-escape')
jfs
@hop: sí. Para detectar entradas no válidas y para compatibilidad con Python 2/3, la cadena se puede codificar explícitamente mediante asciicodificación:\\u0203\u00e4'.encode('ascii').decode('unicode-escape')
jfs
@hop: tu primer comentario (¿Por qué lo has eliminado? No elimines los comentarios que ya han sido respondidos) ya lo dijo. Mi respuesta ( .encode('ascii').decode('unicode-escape')) no depende de sys.getdefaultencoding().
jfs
71

Representar una cadena Unicode como una cadena de bytes se conoce como codificación . Uso u'...'.encode(encoding).

Ejemplo:

    >>> u'æøå'.encode ('utf8')
    '\ xc3 \ x83 \ xc2 \ xa6 \ xc3 \ x83 \ xc2 \ xb8 \ xc3 \ x83 \ xc2 \ xa5'
    >>> u'æøå'.encode ('latin1')
    '\ xc3 \ xa6 \ xc3 \ xb8 \ xc3 \ xa5'
    >>> u'æøå'.encode ('ascii')
    UnicodeEncodeError: el códec 'ascii' no puede codificar caracteres en la posición 0-5: 
    ordinal no en rango (128)

Por lo general, codifica una cadena Unicode cada vez que necesita usarla para E / S, por ejemplo, transferirla a través de la red o guardarla en un archivo de disco.

Convertir una cadena de bytes en una cadena unicode se conoce como decodificación . Use unicode('...', encoding)o '...'. Decodificación (codificación).

Ejemplo:

   >>> u'æøå '
   u '\ xc3 \ xa6 \ xc3 \ xb8 \ xc3 \ xa5' # el intérprete imprime el objeto unicode así
   >>> unicode ('\ xc3 \ xa6 \ xc3 \ xb8 \ xc3 \ xa5', 'latin1')
   u '\ xc3 \ xa6 \ xc3 \ xb8 \ xc3 \ xa5'
   >>> '\ xc3 \ xa6 \ xc3 \ xb8 \ xc3 \ xa5'.decode (' latin1 ')
   u '\ xc3 \ xa6 \ xc3 \ xb8 \ xc3 \ xa5'

Por lo general, decodifica una cadena de bytes cada vez que recibe datos de cadena de la red o de un archivo de disco.

Creo que hay algunos cambios en el manejo de Unicode en Python 3, por lo que lo anterior probablemente no sea correcto para Python 3.

Algunos buenos enlaces:

codeape
fuente
66
No respondiste la pregunta del OP. OP quiere saber qué hacen str.encode () y unicode.decode (). Acabas de repetir lo que se dijo en la pregunta original.
stuckintheshuck
Gran respuesta de por qué en la práctica alguna vez te meterías con la decodificación y codificación. No todas las máquinas entienden el mismo conjunto de caracteres, pero todos entienden los bytes. Codifique en bytes para un idioma que las computadoras entiendan universalmente (y se puedan transferir o guardar en el disco), pero decodifique cuando los humanos realmente tengan que leer esos bytes (por ejemplo, en el lado del cliente).
Alex Petralia
Fantástica respuesta! ¡Esto debería subir!
sandyp
16

anUnicode. encode ('codificación') da como resultado un objeto de cadena y se puede invocar en un objeto unicode

una cuerda. decode ('codificación') da como resultado un objeto unicode y se puede invocar en una cadena, codificada en una codificación dada.


Algunas explicaciones más:

Puede crear algún objeto unicode, que no tiene ningún conjunto de codificación. La forma en que Python lo almacena en la memoria no es de su incumbencia. Puede buscarlo, dividirlo y llamar a cualquier función de manipulación de cadenas que desee.

Pero llega un momento en que desea imprimir su objeto Unicode en la consola o en algún archivo de texto. Por lo tanto, debe codificarlo (por ejemplo, en UTF-8), llama a codificar ('utf-8') y obtiene una cadena con '\ u <someNumber>' dentro, que es perfectamente imprimible.

Luego, nuevamente, le gustaría hacer lo contrario: leer la cadena codificada en UTF-8 y tratarla como Unicode, por lo que el \ u360 sería un carácter, no 5. Luego, decodifica una cadena (con codificación seleccionada) y obtener un nuevo objeto del tipo Unicode.

Solo como nota al margen: puede seleccionar alguna codificación pervertida, como 'zip', 'base64', 'rot' y algunas de ellas se convertirán de una cadena a otra, pero creo que el caso más común es uno que involucra UTF-8 / UTF-16 y cadena.

Abgan
fuente
12

mybytestring.encode (somecodec) es significativo para estos valores de somecodec:

  • base64
  • bz2
  • zlib
  • maleficio
  • quopri
  • rot13
  • string_escape
  • uu

No estoy seguro de para qué sirve decodificar un texto Unicode ya decodificado. Intentar eso con cualquier codificación parece intentar siempre codificar primero con la codificación predeterminada del sistema.

nosklo
fuente
5

Hay algunas codificaciones que se pueden usar para descodificar / codificar de str a str o de unicode a unicode. Por ejemplo base64, hex o incluso rot13. Se enumeran en el módulo de códecs .

Editar:

El mensaje de decodificación en una cadena Unicode puede deshacer la operación de codificación correspondiente:

In [1]: u'0a'.decode('hex')
Out[1]: '\n'

El tipo devuelto es str en lugar de unicode, lo cual es desafortunado en mi opinión. Pero cuando no está haciendo una decodificación / decodificación adecuada entre str y unicode, esto parece un desastre de todos modos.


fuente
1
-1: El método de decodificación no se aplica al objeto unicode. En cambio, el objeto Unicode se codifica como una cadena de bytes 'ascii', antes de que comience la operación de decodificación. Para una prueba de esa afirmación, intente u'ã'.decode ('hex'), que produce UnicodeEncodeError
nosklo
2
@nosklo: Tienes razón. Lo que realmente quise decir es que los objetos unicode tienen un método decode () para que también puedas aplicarles códecs sin codificación de caracteres. Todo este negocio de codificación sin caracteres hace que esta interfaz sea un desastre en Python <3.
1

La respuesta simple es que son exactamente lo opuesto el uno del otro.

La computadora usa la unidad básica de byte para almacenar y procesar información; no tiene sentido para los ojos humanos.

Por ejemplo, '\ xe4 \ xb8 \ xad \ xe6 \ x96 \ x87' es la representación de dos caracteres chinos, pero la computadora solo sabe (es decir, imprimir o almacenar) que son caracteres chinos cuando se les da un diccionario para buscarlos. Palabra china, en este caso, es un diccionario "utf-8", y no podría mostrar correctamente la palabra china deseada si busca en un diccionario diferente o incorrecto (utilizando un método de decodificación diferente).

En el caso anterior, el proceso para que una computadora busque palabras chinas es decode() .

Y el proceso de la computadora escribiendo los chinos en la memoria de la computadora es encode() .

Entonces, la información codificada son los bytes sin procesar, y la información decodificada son los bytes sin procesar y el nombre del diccionario a referencia (pero no el diccionario en sí).

Bahía Eren
fuente