2010-05-30 4 views
1

Sur les fenêtres, j'ai le problème suivant:Un UnicodeDecodeError qui se produit avec JSON en python sous Windows, mais pas Mac

>>> string = "Don´t Forget To Breathe" 
>>> import json,os,codecs 
>>> f = codecs.open("C:\\temp.txt","w","UTF-8") 
>>> json.dump(string,f) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "C:\Python26\lib\json\__init__.py", line 180, in dump 
    for chunk in iterable: 
    File "C:\Python26\lib\json\encoder.py", line 294, in _iterencode 
    yield encoder(o) 
UnicodeDecodeError: 'utf8' codec can't decode bytes in position 3-5: invalid data 

(Notez lapostrophe non-ascii dans la chaîne.)

Cependant , mon ami, sur son mac (également en utilisant python2.6), peut courir à travers cela comme un jeu d'enfant:

> string = "Don´t Forget To Breathe" 
> import json,os,codecs 
> f = codecs.open("/tmp/temp.txt","w","UTF-8") 
> json.dump(string,f) 
> f.close(); open('/tmp/temp.txt').read() 
'"Don\\u00b4t Forget To Breathe"' 

Pourquoi est-ce? J'ai également essayé d'utiliser UTF-16 et UTF-32 avec json et codecs, mais en vain.

Répondre

2

Que montre repr(string) sur chaque machine? Sur mon Mac, l'apostrophe montre \xc2\xb4 (codage utf8, 2 octets) donc bien sûr le codec utf8 peut gérer cela; sur votre Windows il ne fait clairement pas cela puisqu'il parle de trois octets étant un problème - ainsi sur Windows vous devez avoir un autre jeu d'encodage non-utf8 pour votre console.

Votre problème général est que, dans le pré-3 Python, vous ne devriez pas entrer dans une chaîne d'octets ("...." que vous avez utilisé, plutôt que u"....") avec un contenu non-ascii (sauf indication sous forme de chaînes d'échappement): cela peut (selon sur la façon dont la session est définie) échouent directement ou produisent des octets, selon certains codecs définis par défaut, qui ne sont pas exactement les octets que vous attendez (parce que vous n'êtes pas conscient du codec par défaut utilisé). Utilisez littéraux Unicode explicites

string = u"Don´t Forget To Breathe" 

et vous devriez être OK (ou si vous avez un problème, il émergera droit au moment de cette mission, à quel point on peut aller dans la question de « comment je définir un encodage par défaut pour mes sessions interactives "si c'est ce dont vous avez besoin".

+0

Hm. Fait intéressant, cela fonctionne. Cependant, dans l'implémentation actuelle avec laquelle je travaille (le code ci-dessus n'était qu'un exemple isolé), ce que j'essaie réellement de sérialiser avec json est un objet créé par cette fonction: http://pastebin.com/e0CNAvCE Parcourez un répertoire, recherchez tous les fichiers MP3 et créez un dictionnaire à partir de leurs métadonnées. Naturellement, il y aura des caractères spéciaux, mais je pensais avoir déjà traité cette possibilité en encapsulant unicode() autour des métadonnées. Existe-t-il une façon dont mon approche unicode() dans cette fonction est différente de l'exemple u ""? – ventolin

+0

@ventolin, no: les appels 'unicode' eux-mêmes devraient immédiatement échouer chaque fois que leur argument contient des caractères non-Ascii (puisque vous ne spécifiez pas d'encodage,' 'ascii'' devrait s'y habituer). Je suis incapable de deviner comment ils pourraient réussir et pourtant la sérialisation de JSON échoue, esp. avec l'erreur ** decode ** que vous signalez (peut-être les ascii des métadonnées mais les _files paths_ ne sont pas ...?) –

Questions connexes