4 votes

Impossible de décoder une chaîne unicode en Python 2.4

Nous sommes en python 2.4. Voici ma situation. Je tire une chaîne de caractères d'une base de données, et elle contient un 'o' tréma ( \xf6 ). À ce stade, si j'exécute type(value), il renvoie str. Je tente ensuite d'exécuter .decode('utf-8'), et j'obtiens une erreur ('utf8' codec can't decode bytes in position 1-4).

Mon objectif ici est de réussir à faire en sorte que type(value) renvoie de l'unicode. J'ai trouvé un question précédente qui contenait des informations utiles, mais l'exemple de la réponse choisie ne semble pas fonctionner pour moi. Y a-t-il quelque chose que je fais mal ici ?

Voici un code à reproduire :

Name = 'w\xc3\xb6rner'.decode('utf-8')
file.write('Name: %s - %s\n' %(Name, type(Name)))

Je n'arrive jamais à l'instruction write, car elle échoue dès la première instruction.

Merci pour votre aide.

Edit :

J'ai vérifié que le jeu de caractères de la base de données est utf8. Dans mon code de reproduction, j'ai donc changé ' \xf6 à \xc3\xb6 ', et l'échec se produit toujours. Y a-t-il une différence entre 'utf-8' et 'utf8' ?

Le conseil sur l'utilisation des codecs pour écrire dans un fichier est pratique (je l'utiliserai certainement), mais dans ce scénario, j'écris uniquement dans un fichier journal à des fins de débogage.

10voto

Jiri Points 4193

Votre chaîne n'est pas en encodage UTF8. Si vous voulez "décoder" une chaîne en unicode, votre chaîne doit être dans l'encodage que vous avez spécifié en paramètre. J'ai essayé cela et cela fonctionne parfaitement :

print 'w\xf6rner'.decode('cp1250')

EDIT

Pour écrire des chaînes unicode dans le fichier, vous pouvez utiliser le module codecs :

import codecs
f = codecs.open("yourfile.txt", "w", "utf8")
f.write( ... )

Il est pratique de spécifier l'encodage de l'entrée/sortie et d'utiliser la chaîne 'unicode' dans tout votre code sans vous soucier des différents encodages.

5voto

vartec Points 53382

C'est évidemment un codage sur un octet. 'ö' en UTF-8 est ' \xc3\xb6 '.

Le codage pourrait être :

  • ISO-8859-1
  • ISO-8859-2
  • ISO-8859-13
  • ISO-8859-15
  • Win-1250
  • Win-1252

3voto

Staale Points 8795

Vous devez utiliser "ISO-8859-1" :

Name = 'w\xf6rner'.decode('iso-8859-1')
file.write('Name: %s - %s\n' %(Name, type(Name)))

utf-8 utilise 2 octets pour l'échappement de tout ce qui n'est pas ascii, mais ici c'est juste 1 octet, donc iso-8859-1 est probablement correct.

2voto

bobince Points 270740

Dans mon code de reproduction, j'ai donc changé ' \xf6 à \xc3\xb6 et l'échec se produit toujours

Pas dans la première ligne :

>>> 'w\xc3\xb6rner'.decode('utf-8')
u'w\xf6rner'

La deuxième ligne sera cependant erronée :

>>> file.write('Name: %s - %s\n' %(Name, type(Name)))
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf6' in position 7: ordinal not in range(128)

C'est tout à fait ce à quoi on s'attendrait en essayant d'écrire des caractères Unicode non-ASCII dans un flux d'octets. Si vous utilisez la suggestion de Jiri d'un flux enveloppé de codecs, vous pouvez écrire l'Unicode directement, sinon vous devrez ré-encoder la chaîne Unicode en octets manuellement.

Pour les besoins de la journalisation, il serait préférable d'envoyer simplement un repr() de la variable. Ainsi, vous n'avez pas à vous soucier de la présence de caractères Unicode, de sauts de ligne ou d'autres caractères indésirables :

name= 'w\xc3\xb6rner'.decode('utf-8')
file.write('Name: %r\n' % name)

Name: u'w\xf6rner'

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X