2009-04-27 3 views
4

J'ai terminal.app configuré pour accepter utf-8 et dans bash je peux taper des caractères unicode, les copier et les coller, mais si je démarre le python shell Je ne peux pas et si j'essaie de décoder unicode Je reçois des erreurs:Impossible de décoder la chaîne utf-8 en python sur os x terminal.app

>>> wtf = u'\xe4\xf6\xfc'.decode() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128) 
>>> wtf = u'\xe4\xf6\xfc'.decode('utf-8') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/encodings/utf_8.py", line 16, in decode 
    return codecs.utf_8_decode(input, errors, True) 
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128) 

Quelqu'un sait ce que je fais mal?

+0

[Ce] (http://stackoverflow.com/ questions/368805/python-unicodedecodeerror-am-i-malentendu-encoder/370199 # 370199) répondre dans une question connexe sur l'encodage/décodage pourrait être utile. – tzot

Répondre

18

Je pense qu'il ya encode/decode la confusion dans tous les sens. Vous commencez avec un objet unicode:

u'\xe4\xf6\xfc' 

Ceci est un objet unicode, les trois personnages sont les points de code unicode pour « aou ». Si vous voulez les transformer en utf-8, vous devez encode les:

>>> u'\xe4\xf6\xfc'.encode('utf-8') 
'\xc3\xa4\xc3\xb6\xc3\xbc' 

Les six caractères résultants sont la représentation utf-8 "aou".

Si vous appelez decode(...), vous essayez d'interpréter les caractères comme un codage qui doit encore être converti en unicode. Comme il est déjà Unicode, cela ne fonctionne pas. Votre premier appel tente une conversion Ascii en Unicode, le second appel une conversion Utf-8 en Unicode. Puisque u'\xe4\xf6\xfc' n'est ni Ascii valide ni Utf-8 valide, ces tentatives de conversion échouent.

Une autre confusion pourrait provenir du fait que '\xe4\xf6\xfc' est également le codage Latin1/ISO-8859-1 de "äöü". Si vous écrivez une chaîne de python normale (sans le « u » qui marque comme unicode), vous pouvez le convertir en un objet unicode avec decode('latin1'):

>>> '\xe4\xf6\xfc'.decode('latin1') 
u'\xe4\xf6\xfc' 
+1

aha. Cela a finalement du sens. –

+0

D'accord. Le sens a été fait. –

4

Je pense que vous avez l'encodage et le décodage en arrière. Vous codez Unicode dans un flux d'octets et décodez le flux d'octets en Unicode.

Python 2.6.1 (r261:67515, Dec 6 2008, 16:42:21) 
[GCC 4.0.1 (Apple Computer, Inc. build 5370)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> wtf = u'\xe4\xf6\xfc' 
>>> wtf 
u'\xe4\xf6\xfc' 
>>> print wtf 
äöü 
>>> wtf.encode('UTF-8') 
'\xc3\xa4\xc3\xb6\xc3\xbc' 
>>> print '\xc3\xa4\xc3\xb6\xc3\xbc'.decode('utf-8') 
äöü 
+1

Um. UTF-8 est un flux d'octets déjà encodé, donc, bien qu'il ne soit pas en arrière, vous l'avez au moins latéralement :) Peut-être que vous vouliez dire Unicode au lieu de UTF-8. Je vais éditer votre message et vous laisser décider. – tzot

+0

Oui, vous avez raison. Merci! –

2

La section Unicode strings du didacticiel d'introduction explique bien:

pour convertir une chaîne de caractères Unicode en une chaîne de 8 bits en utilisant un codage spécifique, les objets Unicode fournissent une méthode encode() qui prend un argument, le nom de l'encodage. Les noms en minuscules pour les codages sont préférés.

>>> u"äöü".encode('utf-8') 
'\xc3\xa4\xc3\xb6\xc3\xbc' 
+1

ne décodez-vous pas les caractères dans votre dernière ligne? –

+0

Oui, j'ai enlevé ma fatigue fatidique, la section des cordes unicode l'explique mieux que je peux .. – dbr

3
>>> wtf = '\xe4\xf6\xfc' 
>>> wtf 
'\xe4\xf6\xfc' 
>>> print wtf 
��� 
>>> print wtf.decode("latin-1") 
äöü 
>>> wtf_unicode = unicode(wtf.decode("latin-1")) 
>>> wtf_unicode 
u'\xe4\xf6\xfc' 
>>> print wtf_unicode 
äöü