Je suis vraiment confus. J'ai essayé d'encoder mais l'erreur disait can't decode...
.
>>> "你好".encode("utf8")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)
Je sais comment éviter l'erreur avec le préfixe "u" sur la chaîne. Je me demande simplement pourquoi l'erreur est "impossible à décoder" quand l'encodage a été appelé. Que fait Python sous le capot?
"你好".encode('utf-8')
encode
convertit un objet unicode en un objet string
. Mais ici vous l'avez invoqué sur un objet string
(car vous n'avez pas le u). Donc, python doit d'abord convertir la string
en un objet unicode
. Donc, cela équivaut à
"你好".decode().encode('utf-8')
Mais le décodage échoue car la chaîne n'est pas valide en ascii. C'est pourquoi vous recevez une plainte concernant l'impossibilité de décoder.
Toujours encoder de Unicode en octets.
.__ Dans ce sens, vous choisissez l’encodage.
>>> u"你好".encode("utf8")
'\xe4\xbd\xa0\xe5\xa5\xbd'
>>> print _
你好
L'autre façon consiste à décoder d'octets en unicode.
Dans cette direction, vous devez savoir ce qu'est l'encodage}.
>>> bytes = '\xe4\xbd\xa0\xe5\xa5\xbd'
>>> print bytes
你好
>>> bytes.decode('utf-8')
u'\u4f60\u597d'
>>> print _
你好
Ce point ne peut pas être assez souligné. Si vous voulez éviter de jouer à l'unicode "whack-a-mole", il est important de comprendre ce qui se passe au niveau des données. Ici, il est expliqué d'une autre manière:
decode
dessus.encode
dessus.Désormais, après avoir vu .encode
sur une chaîne d'octets, Python 2 commence par tenter de la convertir implicitement en texte (un objet unicode
). De même, en voyant .decode
sur une chaîne unicode, Python 2 tente implicitement de la convertir en octets (un objet str
).
Ces conversions implicites expliquent pourquoi vous pouvez obtenir Unicode
Decode
Error
lorsque vous avez appelé encode
. C'est parce que l'encodage accepte généralement un paramètre de type unicode
; lors de la réception d'un paramètre str
, il y a un décodage implicite dans un objet de type unicode
avant de le recoder à l'aide d'un autre encodage. Cette conversion choisit un décodeur 'ascii' par défaut†, vous donnant l'erreur de décodage à l'intérieur d'un encodeur.
En fait, dans Python 3, les méthodes str.decode
et bytes.encode
n'existent même pas. Leur élimination était une tentative [controversée] d'éviter cette confusion commune.
†... ou ce que le code sys.getdefaultencoding()
mentionne; généralement c'est 'ascii'
Vous pouvez essayer ceci
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
Ou
Vous pouvez également essayer de suivre
Ajoutez la ligne suivante en haut de votre fichier .py.
# -*- coding: utf-8 -*-
Si vous utilisez Python <3, vous devrez dire à l'interprète que votre littéral de chaîne est Unicode en le préfixant avec un u
:
Python 2.7.2 (default, Jan 14 2012, 23:14:09)
[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> "你好".encode("utf8")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)
>>> u"你好".encode("utf8")
'\xe4\xbd\xa0\xe5\xa5\xbd'
Lectures supplémentaires: Unicode HOWTO .
Vous utilisez u"你好".encode('utf8')
pour coder une chaîne unicode . Mais si vous souhaitez représenter "你好"
, vous devez le décoder. Juste comme:
"你好".decode("utf8")
Vous obtiendrez ce que vous voulez. Peut-être devriez-vous en savoir plus sur l'encodage et le décodage.
Si vous utilisez Unicode, parfois, au lieu de encode('utf-8')
, vous pouvez également essayer d’ignorer les caractères spéciaux, par exemple.
"你好".encode('ascii','ignore')
ou en tant que something.decode('unicode_escape').encode('ascii','ignore')
comme suggéré ici .
Pas particulièrement utile dans cet exemple, mais peut mieux fonctionner dans d'autres scénarios lorsqu'il n'est pas possible de convertir certains caractères spéciaux.
Vous pouvez également envisager de remplacer un caractère particulier par replace()
.
Si vous démarrez l'interpréteur python à partir d'un shell sous Linux ou de systèmes similaires (BSD, vous ne savez pas si Mac), vérifiez également le codage par défaut du shell.
Appelez locale charmap
depuis le shell (pas l’interpréteur python) et vous devriez voir
[user@Host dir] $ locale charmap
UTF-8
[user@Host dir] $
Si ce n'est pas le cas et que vous voyez autre chose, par exemple
[user@Host dir] $ locale charmap
ANSI_X3.4-1968
[user@Host dir] $
Python héritera (du moins dans certains cas, comme dans le mien) du codage du shell et ne pourra pas imprimer (certains? Tous?) Des caractères Unicode. Le codage par défaut de Python que vous voyez et contrôlez via sys.getdefaultencoding()
et sys.setdefaultencoding()
est dans ce cas ignoré.
Si vous constatez que vous avez ce problème, vous pouvez le résoudre en
[user@Host dir] $ export LC_CTYPE="en_EN.UTF-8"
[user@Host dir] $ locale charmap
UTF-8
[user@Host dir] $
(Vous pouvez également éditer le /etc/locale.conf
(ou le fichier régissant la définition des paramètres régionaux dans votre système) pour corriger ce problème.