web-dev-qa-db-fra.com

Quelle est la différence entre encoder/décoder?

Je n'ai jamais été sûr de comprendre la différence entre le décodage str/unicode et le codage.

Je sais que str().decode() est pour lorsque vous avez une chaîne d'octets que vous savez a un certain encodage de caractères, étant donné que le nom d'encodage, il retournera une chaîne unicode.

Je sais que unicode().encode() convertit les caractères unicode en une chaîne d'octets en fonction d'un nom de codage donné.

Mais je ne comprends pas à quoi servent str().encode() et unicode().decode(). Quelqu'un peut-il expliquer, et éventuellement aussi corriger tout ce que je me suis trompé ci-dessus?

MODIFIER:

Plusieurs réponses donnent des informations sur ce que .encode fait sur une chaîne, mais personne ne semble savoir ce que .decode fait pour unicode.

169
ʞɔıu

La méthode decode des chaînes unicode n'a vraiment aucune application (sauf si vous avez des données non textuelles dans une chaîne unicode pour une raison quelconque - voir ci-dessous). C'est principalement pour des raisons historiques, je pense. En Python 3, il est complètement parti.

unicode().decode() effectuera un encodage de s implicite à l'aide du codec par défaut (ascii). Vérifiez ceci comme si:

>>> 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)

Les messages d'erreur sont exactement les mêmes.

Pour str().encode() c'est l'inverse - il tente un décodage de s implicite avec le codage par défaut:

>>> 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)

Utilisé comme ceci, str().encode() est également superflu.

Mais il existe une autre application de cette dernière méthode qui est utile: il existe des encodings qui n'ont rien à voir avec les jeux de caractères, et qui peuvent donc être appliqués aux chaînes de 8 bits de manière significative:

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

Vous avez cependant raison: l'utilisation ambiguë du "codage" pour ces deux applications est ... maladroite. Encore une fois, avec les types byte et string séparés dans Python 3, le problème ne se pose plus.

99
user3850

Représenter une chaîne unicode sous forme de chaîne d'octets est appelé codage. Utilisez u'...'.encode(encoding).

Exemple:

 >>> 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: le codec 'ascii' ne peut pas coder les caractères en position 0-5: 
 l'ordinal n'est pas dans la fourchette (128) 

En général, vous codez une chaîne unicode chaque fois que vous devez l’utiliser pour IO, par exemple pour la transférer sur le réseau ou pour l’enregistrer sur un fichier de disque.

Convertir une chaîne d'octets en chaîne unicode est appelé décodage. Utilisez unicode('...', encoding) ou '...'. Decode (encoding).

Exemple:

 >>> u'æøå '
 u '\ xc3\xa6\xc3\xb8\xc3\xa5' # l'interpréteur imprime l'objet unicode comme suit 
 >>> 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' 

Vous décodez généralement une chaîne d'octets chaque fois que vous recevez des données de chaîne du réseau ou d'un fichier de disque.

Je pense qu’il ya quelques changements dans la gestion de l’unicode dans Python 3, ce qui précède n’est probablement pas correct pour Python 3.

Quelques bons liens:

68
codeape

anUnicode .encoder ('encoding') résulte en un objet string et peut être appelé sur un objet unicode 

aString .decode ('encoding') résulte en un objet unicode et peut être appelé sur une chaîne, encodée dans un encodage donné.


Quelques explications supplémentaires:

Vous pouvez créer un objet unicode, pour lequel aucun ensemble de codage n'est défini. La façon dont il est stocké par Python en mémoire ne vous concerne pas. Vous pouvez le rechercher, le diviser et appeler n'importe quelle fonction de manipulation de chaîne que vous aimez.

Mais il arrive un moment où vous souhaitez imprimer votre objet unicode sur la console ou dans un fichier texte. Vous devez donc encoder (par exemple, en UTF-8), appeler encode ('utf-8') et obtenir une chaîne contenant '\ u <someNumber>', qui est parfaitement imprimable.

Puis, encore une fois - vous voudriez faire l’opposé - lire une chaîne encodée en UTF-8 et la traiter comme un Unicode, de sorte que le\u360 serait un caractère et non pas 5. Ensuite, vous décoderez codage sélectionné) et obtenez un nouvel objet de type Unicode.

Juste comme note latérale - vous pouvez sélectionner un encodage pervers, comme 'Zip', 'base64', 'rot' et certains d'entre eux seront convertis de chaîne en chaîne, mais je pense que le cas le plus courant est celui impliquant UTF-8/UTF-16 et chaîne.

15
Abgan

mybytestring.encode (somecodec) est significatif pour ces valeurs de somecodec:

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

Je ne sais pas à quoi sert le décodage d'un texte unicode déjà décodé. Essayer avec n'importe quel encodage semble toujours essayer de coder d'abord avec le codage par défaut du système.

12
nosklo

Vous devriez lire Python UnicodeDecodeError - Est-ce que je comprends mal l'encodage . Ma compréhension de l’unicode en Python était bien plus claire après avoir lu la réponse acceptée.

8
Oli

Quelques codages peuvent être utilisés pour décoder/encoder de str à str ou d'unicode à unicode. Par exemple, base64, hex ou même rot13. Ils sont listés dans le module codecs .

Modifier:

Le message de décodage sur une chaîne unicode peut annuler l'opération de codage correspondante:

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

Le type retourné est str au lieu de unicode, ce qui est regrettable à mon avis. Mais quand vous ne faites pas un bon décodage entre str et unicode, cela ressemble quand même à un gâchis.

5
unbeknown

La réponse simple est qu'ils sont l'exact opposé de l'autre.

l'ordinateur utilise l'unité d'octet de base pour stocker et traiter les informations, cela n'a pas de sens pour les yeux.

par exemple, '\ xe4\xb8\xad\xe6\x96\x87' est la représentation de deux caractères chinois, mais l'ordinateur ne sait que (qui veut dire imprimer ou stocker) que ce sont des caractères chinois lorsqu'un dictionnaire leur est demandé Le mot chinois, dans ce cas, il s’agit d’un dictionnaire "utf-8" et il ne pourrait pas afficher correctement le mot chinois voulu si vous recherchez un dictionnaire différent ou incorrect (en utilisant une méthode de décodage différente). 

Dans le cas ci-dessus, le processus permettant à un ordinateur de rechercher le mot chinois est décodage (). 

Et le processus qui consiste à écrire le chinois dans la mémoire d’un ordinateur est codé ().

ainsi, les informations de codage sont les octets bruts et les informations décodées sont les octets bruts et le nom du dictionnaire à référencer (mais pas le dictionnaire lui-même).

0
Eren Bay