IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

UnicodeEncodeError: 'ascii' codec: problème classique mais…


Sujet :

Python

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    124
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2006
    Messages : 124
    Points : 87
    Points
    87
    Par défaut UnicodeEncodeError: 'ascii' codec: problème classique mais…
    Bonjour à tous,

    Je débute en Python parce que mes travaux d'étudiants m'amènent à utiliser networkX pour l'analyse de graphes.

    J'ai un problème avec des chaînes unicodes provenant de fichiers graphml (xml donc). En voici un à titre d'exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <graphml xmlns="http://graphml.graphdrawing.org/xmlns">
      <key attr.name="label" attr.type="string" for="node" id="d1"/>
      <graph edgedefault="directed" id="G">
        <node id="1">
          <data key="d1">A name with unicode: «é è» </data>
        </node>
      </graph>
    </graphml>
    Si je lis ce fichier et que je tente d'imprimer la chaîne sur la sortie standard, je n'ai pas de problèmes. Par contre, si je redirige vers un fichier ou un pipe, j'ai le message d'erreur plus bas.

    Le script de lecture-affichage:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
     
    import sys
    import networkx as nx
     
    input_file = sys.argv[1]
    G = nx.read_graphml(path=input_file)
     
    label = G.node['1']['label']
    print type(label)
    print label
    Le résultat:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    $ ./test.py single.graphml
    <type 'unicode'>
    A name with unicode: «é è»
    $ ./test.py single.graphml > /dev/null
    <type 'unicode'>
    Traceback (most recent call last):
      File "./test.py", line 12, in <module>
        print label
    UnicodeEncodeError: 'ascii' codec can't encode characters in position 21-22: ordinal not in range(128)
    $ ./test.py single.graphml | less
    <type 'unicode'>
    Traceback (most recent call last):
      File "./test.py", line 12, in <module>
        print label
    UnicodeEncodeError: 'ascii' codec can't encode characters in position 21-22: ordinal not in range(128)
    $ set | grep LANG
    LANG=fr_BE.UTF-8
    LANGUAGE=fr_BE:fr
    Si au lieu de passer par la sortie standard, j'écris directement dans un descripteur de fichier, le problème est le même:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    f = open('foo', 'a')
    f.write(label)
    Je travaille sous Debian Wheezy. L'encodage dans le terminal n'a jamais posé de problèmes.
    Si quelqu'un a une piste…

    Merci d'avance,

    G.

  2. #2
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    salut,

    Faut préciser l'encodage:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    >>> txt = u'éàôï'
    >>> with open('text', 'w') as outf:
    ...     outf.write(txt.encode('utf-8'))

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    124
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2006
    Messages : 124
    Points : 87
    Points
    87
    Par défaut UnicodeEncodeError: 'ascii' codec: problème classique mais…
    Citation Envoyé par VinsS Voir le message
    salut,

    Faut préciser l'encodage:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    >>> txt = u'éàôï'
    >>> with open('text', 'w') as outf:
    ...     outf.write(txt.encode('utf-8'))
    Merci.

    Et si je veux rediriger la sortie standard simplement via un pipe, sans ouvrir un descripteur dans le script ?

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Février 2012
    Messages
    48
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2012
    Messages : 48
    Points : 105
    Points
    105
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    serge@debianThinkpad:~$ python -c "print(u'é')" 
    é
    serge@debianThinkpad:~$ python -c "print('é')"
    é
    serge@debianThinkpad:~$ python -c "print(u'é')"
    é
    serge@debianThinkpad:~$ python -c "print('é')" > /dev/null 
    serge@debianThinkpad:~$ python -c "print(u'é')" > /dev/null 
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
    UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
    serge@debianThinkpad:~$ python -c "print(u'é'.encode('utf-8'))" > /dev/null
    La solution de ton problème est très simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    # -*- coding: utf-8 -*-
    Ce code au début de chacun de tes fichiers. Et vérifie aussi que l'encodage de ton code source est bien en utf-8.
    Si ça ne résolve pas le problème, alors, laisse cette indication d'encodage et encode ta chaine de caractère unicode en utf-8 comme je l'ai fais en dernière ligne. Ce que tu reçois de networkx, c'est de l'unicode.

    L'explication est plus compliqué, et je dois avouer que je ne connais pas trop cette partie de la mécanique de python, n'ayant jamais été confronté à cela (des problèmes d'unicode provenant de base de données ou de fichiers pourris, j'en bouffe par paquets de 10 tout les jours à mon travail, mais des problèmes d'encodage dans le code source même de mon programme, jamais).
    Il ne faut surtout pas hésiter à me corriger ou apporter des explications, ça m'intéresse. La majeur partie de ce que je vais dire est une hypothèse de ma part.

    Mon système est aussi en utf-8. Et pourtant, j'ai la première ligne qui affiche "é". Pourquoi ? C'est typiquement une erreur qui est souvent rencontrée en php, car ça correspond à de l'utf-8 brutalement encodée depuis du latin-1. Mais d'où sort le latin-1 ici ? Mon système est en utf-8, ce que je reçoit du monde extérieur est de l'utf-8.
    Par défaut, python va considérer que ton code source est en latin-1 (de mémoire, et je n'en suis plus trop sûr) si aucune indication ne lui est donné en début de fichier. Dont ta chaine de caractère 'é'. Il va donc décoder du latin-1 depuis une source en utf-8 (dans mon cas, l'entrée de la console, dans ton cas, ton code source), et de l'afficher en utf-8 (l'encodage de ton système, où aboutit la sortie standard stdout), d'où le "é". Rien que le fait de faire un print va modifier ce que tu vois, et ce que tu vois est une interprétation de ce qui se passe dans la cuisine de python, mais ce n'est pas la réalité de ta chaine de caractère dans la mémoire de ton pc.
    Pure supposition de ma part, quand tu fais un pipe, je pense que l'encodage de la sortie standard stdout n'est plus utf-8 mais ascii (pourquoi ?). Et par conséquent, Python aime pas que tu balances n'importe quoi n'importe comment au niveau des encodages et il te balance une erreur.

    Si tu as du mal à comprendre l'histoire du stdout, dis-toi que chaque fois que tu fais un print, en réalité, tu écris dans un fichier. Un fichier spécial, certes, mais un fichier. D'ailleurs, en passant par sys.stdout, pour écrire sur la sortie standard, on fait un sys.stdout.write(ma_string). Et un fichier ne comprends pas l'unicode tel quel, il a besoin d'octets (en gros, unicode=chaine de caractère, str=suite d'octet. C'est pour cela qu'en python3, cette confusion a été évité en dégageant le type str tel qu'on le connaissait).

    Désolé du coté décousu de l'explication. Mais tu as la solution, c'est déjà ça.

Discussions similaires

  1. Réponses: 16
    Dernier message: 31/07/2012, 16h01
  2. UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9'
    Par slaima15 dans le forum Général Python
    Réponses: 4
    Dernier message: 06/06/2011, 23h18
  3. UnicodeEncodeError: 'ascii' codec can't encode character
    Par WebTotoche dans le forum Général Python
    Réponses: 5
    Dernier message: 06/04/2011, 08h58
  4. 'ascii' codec can't decode byte
    Par Bibicmoi dans le forum Général Python
    Réponses: 5
    Dernier message: 28/08/2007, 23h15
  5. [Javadoc]La Javadoc et un problème... simple mais paralysant
    Par lionrouge dans le forum Eclipse Java
    Réponses: 2
    Dernier message: 09/12/2005, 00h00

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo