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 :

erreur de conversion unicode sur redirection de sortie dans un fichier


Sujet :

Python

  1. #1
    Candidat au Club
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Décembre 2012
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4
    Points : 3
    Points
    3
    Par défaut erreur de conversion unicode sur redirection de sortie dans un fichier
    J'ai vu des quantités de pages sur le sujet, mais aucune traitant de mon problème en particulier.

    Un print correct dans ma fenêtre terminal sort en erreur lorsque je redirige la sortie dans un fichier.
    J'ai vu des tonnes d'exemples avec un encoding en UTF8, mais pour toutes sortes de raisons je souhaite rester en ISO-8859.
    Ma seconde contrainte est que, dans la pratique, je récupère des chaînes codées en unicode à travers une API.
    Je ne suis donc pas maître de l'encodage d'origine.

    Exemple trivial :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $ cat test.py
    #!/usr/bin/env python
    print u'voil\xe0'
    Ma langue :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $ locale
    LANG=fr_FR.iso885915@euro
    ...
    Sortie correcte dans ma fenêtre terminal courante :
    Et maintenant la même chose en redirigeant la sortie dans un fichier :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $ ./test.py > xxx
    Traceback (most recent call last):
      File "./test.py", line 3, in <module>
        print u'voil\xe0'
    UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 4: ordinal not in range(128)
    Enfin, tous les tests de conversion du type encode("ascii") se soldent par des échecs.
    Il y a bien l'option "replace" (ou "ignore") qui fonctionne, mais du coup je perds les accents.

    Des idées ?

  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,

    Suffit d'un peu de méthode.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    #-*- coding: utf-8 -*-
     
    l = u'Déjà-vu'
    print l
    with open('test1', 'w') as outf:
        outf.write(l.encode('utf-8', 'replace'))
    with open('test1', 'r') as inf:
        print inf.read()
    print 'Done'
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    vincent@tiemoko:~/Bureau$ python test.py 
    Déjà-vu
    Déjà-vu
    Done

  3. #3
    Candidat au Club
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Décembre 2012
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4
    Points : 3
    Points
    3
    Par défaut
    Merci VinsS, mais si j'avais voulu faire de l'utf8 je n'aurai pas créé ce topic.
    Comme je l'ai dis avant : "je ne souhaite pas passer en utf8".

    Mais comme je suis tétu j'ai continué à chercher et j'ai finalement trouvé la solution.

    En fait le problème venait du fait qu'en redirigeant stdout dans un fichier au niveau du shell, l'encodage était celui du système au lieu de mon environnement.
    Or un "getdefaultencoding()" me retournait "None" malgré un positionnement correct au niveau système.
    Du coup l'idée était de modifier l'encoding par défaut dans le programme.
    Le problème était que la fonction setdefaultencoding() du module sys ne marchait pas.
    J'ai trouvé quelque part l'astuce consistant à recharger le module sys juste avant !

    Voici donc la solution :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #!/usr/bin/env python
    import sys
    reload(sys)
    sys.setdefaultencoding('iso8859_15')
    print u'voil\xe0'
    Et là ça marche aussi bien dans ma fenêtre qu'en redirigeant la sortie dans un fichier.

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Salut,

    Citation Envoyé par adonf92 Voir le message
    Le problème était que la fonction setdefaultencoding() du module sys ne marchait pas.
    J'ai trouvé quelque part l'astuce consistant à recharger le module sys juste avant !
    Cet article vous explique pourquoi cette astuce est dangereuse.

    Citation Envoyé par adonf92 Voir le message
    J'ai vu des quantités de pages sur le sujet, mais aucune traitant de mon problème en particulier.
    Et pourtant! Tout ce que vous devez savoir sur Python et l'Unicode est dans leUnicode How to que vous trouvez dans la documentation Python.
    Inutile de trier sur le Web tout ce qui parle de Python et d'Unicode pour voir si çà s'applique à votre cas: tout est dans ce document.

    Et si vous l'appliquez, il faut ouvrir le fichier en précisant l'encoding souhaité (un peu comme VinsS a essayé de vous le montrer avec un autre encoding).
    Comme vous êtes en 2.7, le document recommande aussi d'utiliser codecs.open au lieu de l'open standard.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Candidat au Club
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Décembre 2012
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4
    Points : 3
    Points
    3
    Par défaut erreur de conversion unicode sur redirection de stdout
    Merci pour ces précisions wiztricks.

    Je savais en effet grâce au Unicode Howto comment lire et écrire dans des fichiers à travers la fonction open().
    Le problème est que je ne fais pas d'open. C'est le shell qui redirige stdout (à travers la crontab) sur un fichier qu'il ouvre lui-même.
    Or l'encodage de stdout dans le module sys est en read only.
    Sauf erreur de ma part, je n'ai vu aucune référence dans les docs à cette problématique qui est à la frontière du langage et du système.
    C'est en constatant que l'encodage par défaut était à None lors d'une redirection que j'ai eu l'idée de rechercher dans cette direction.
    Et là je suis tombé sur ce fameux setdefaultencoding().

    Enfin j'ai bien conscience qu'il serait préférable ne pas utiliser cette fonction, mais je n'ai rien trouvé d'autre que ce work-around.
    Je suis toujours preneur d'une solution "propre"
    L'idée étant de modifier l'encodage de sys.stdout ...

    En résumé voici une autre manière, plus simple, de décrire le problème :
    (avec bien sûr la contrainte de rester en ISO-8859 et python2.7)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    $ echo $LANG
    fr_FR.iso885915
    $ python -c "print u'voil\xe0'"
    voilà
    $ python -c "print u'voil\xe0'" > xxx
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
    UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 4: ordinal not in range(128)

  6. #6
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Citation Envoyé par adonf92 Voir le message
    Le problème est que je ne fais pas d'open. C'est le shell qui redirige stdout (à travers la crontab) sur un fichier qu'il ouvre lui-même.
    Or l'encodage de stdout dans le module sys est en read only.
    Certes mais rien ne vous empêche d'écrire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    python -c "print u'voil\xe0'.encode('latin-1')" > xxx
    ou de changer l'encoding de sys.stdout:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    >>> import sys
    >>> import codecs
    >>> sys.stdout = codecs.getwriter('latin-1')(sys.stdout)
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  7. #7
    Candidat au Club
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Décembre 2012
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4
    Points : 3
    Points
    3
    Par défaut
    Excellent !!! Merci wiztricks

    La 1ère solution n'est pas applicable dans mon cas.
    En revanche la seconde fonctionne parfaitement et est tout à fait adéquate.

    Encore merci grand maître

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 6
    Dernier message: 18/09/2014, 13h43
  2. Conversion Unicode sur TServerSocket
    Par Higgins dans le forum Langage
    Réponses: 2
    Dernier message: 24/06/2014, 09h14
  3. sortie du script sur l'écran et dans un fichier
    Par dubis dans le forum Programmation et administration système
    Réponses: 2
    Dernier message: 22/02/2012, 15h52
  4. [ASE 12.5.1] Redirection de PRINT dans un fichier de log
    Par zayro dans le forum Adaptive Server Enterprise
    Réponses: 1
    Dernier message: 21/04/2006, 12h48
  5. Réponses: 2
    Dernier message: 27/12/2005, 13h52

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