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 :

Problème unicode / caractères spéciaux + écriture de fichier


Sujet :

Python

  1. #1
    Membre confirmé Avatar de Mysti¢
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    155
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 155
    Par défaut Problème unicode / caractères spéciaux + écriture de fichier
    Bonjour,

    Alors pour rentrer dans le vif du sujet, rien de mieux que quelques lignes de code :]

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    >>> tab = ['é','à']
    >>> f = open('sortie.txt', 'w')
    >>> f.write(str(tab))
    >>> f.close()
    Code de sortie.txt : Sélectionner tout - Visualiser dans une fenêtre à part
    ['\x82', '\x85']

    Tout simplement, je souhaiterais récupérer les caractères spéciaux correctement dans mon fichier de sortie.
    Si quelqu'un peut m'éclairer, je lui en serai très reconnaissant. Merci

  2. #2
    Membre confirmé Avatar de Mysti¢
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    155
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 155
    Par défaut
    Ça peut toujours servir à quelqu'un, donc :

    Je rencontrais ce problème avec la version 2.6 de Python, je viens d'essayer avec la 3.1 et les caractères spéciaux sont enregistrés correctement. Reste à voir si j'arrive à installer l'intégralité des librairies que j'utilisais dans mon application pour cette version de Python.

    Edition :

    Etant donné que je n'arrive pas à installer les librairies que je souhaite utiliser pour la version 3.1 de Python, il faut que je trouve une autre alternative...

  3. #3
    Membre chevronné Avatar de Pierre Maurette
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    283
    Détails du profil
    Informations personnelles :
    Âge : 69
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 283
    Par défaut
    Essayez une de ces deux lignes, ou une variation, selon ce que vous souhaitez exactement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    f.write(', '.join(tab))
    f.write("['" + "', '".join(tab) + "']")

  4. #4
    Membre Expert
    Avatar de DelphiManiac
    Homme Profil pro
    Homme à tout faire
    Inscrit en
    Mars 2002
    Messages
    1 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Homme à tout faire
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 147
    Par défaut
    Par défaut sous python 2.6, les chaines de caractères sont encodés en string de 8 bits, sous python 3.1, les chaines de caractères sont en unicode 16 bits.

    Essayes de déclarer ton tableau en unicode :

    Par contre, il faudrait savoir sous quel encodage tu veux enregistrer ton fichier texte. Mais c'est un début de piste entre la différence pyton 2.6 <-> 3.1

    [edit]Voici une version qui ecrit un fichier encodé en utf8.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
     
    import codecs
     
    tab = [u'é',u'à']
    f = codecs.open('sortie.txt', encoding='utf-8', mode='w')
    for c in tab:
        f.write(c)
    f.close()

  5. #5
    Membre confirmé Avatar de Mysti¢
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    155
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 155
    Par défaut
    Tout d'abord, merci pour vos contributions

    Alors concernant la réponse de Pierre, j'ai essayé vos 2 lignes qui je pense me serviront à plusieurs reprise dans mon application, en revanche le problème s'avère un peu plus complexe que ça. Si dans mon exemple j'ai utilisé un tableau, c'était en pensant qu'on pouvait le convertir directement en chaine de caractère, sans avoir à le parcourir et éventuellement mettre en place un système pour le réécrire éléments par élément.

    Ce qui m'emmène à en venir à la suggestion de DelphiManiac. Je pense partir avec le code que tu me donnes en exemple, comme base (d'ailleurs j'avais déjà utilisé la librairie codecs, mais en me compliquant un peu la tâche pour un résultat quasi nul ^^). En fait... les données que je souhaite exporter dans un fichier de sortie, sont surtout sous forme de dictionnaire :

    Par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    {'type' : ' croisière', 'destination' : 'Egypte', 'prix' : '600'} ...
    Pensez vous qu'il y ai une façon de réécrire mon dictionnaire d'une traite ? (un peu comme avec l'appel de la méthode join()) Dans le cas contraire je pense procéder avec un traitement conditionnel à chaque tour de boucle pour conserver la structure de mon dictionnaire.

  6. #6
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 698
    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 698
    Par défaut
    Salut
    Pour sérialiser des structures Python, Pickle fait cela très bien.
    Maintenant, s'il ne s'agit que de dictionnaires, on peut regarder aussi du côté de JSON.
    Reste à savoir combien de ces structures similaires ou pas il faudra stocker et arbitrer sur la pertinence de passer par un SGDB de type SQLite.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  7. #7
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Il ne faut pas confondre l'encodage, tel que Python le fait dans la mémoire ou sur disque, avec ce qui est affiché dans la console d'affichage.

    Actuellement, même si une chaine est correctement encodée, son affichage à l'intérieur d'une liste ou d'un dictionnaire est incorrect:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    z = "abcéèçàù"
    print z
    abcéèçàù 
    print [z]
    ['abc\xe9\xe8\xe7\xe0\xf9']
    La seule manière d'obtenir un affichage correct est de transformer pour l'affichage (et pour l'affichage seulement) la liste en chaine comme par exemple:

    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
    19
    20
    21
    22
     
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    from __future__ import division
     
    import sys
     
    def liste2chaine(L):
        ch = '['
        if ch!=[]:
            for e in L:
                ch += e +  ', '
            ch = ch[:-2]
        ch += ']'
        return ch
     
    x = "abcéèçàù" # ça, c'est en utf-8 à cause du coding
    y = x.decode('utf-8'). encode(sys.stdout.encoding) # y est encodé pour l'affichage
    print y
    abcéèçàù 
    print liste2chaine([y])
    [abcéèçàù]
    Tyrtamos

  8. #8
    Membre confirmé Avatar de Mysti¢
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    155
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 155
    Par défaut
    Merci pour vos contributions,

    Concernant celle de wiztricks, je ne connaissais pas Pickle, mais par rapport aux aperçus de la documentation que j'ai pu avoir je pense que ça peut m'intéresser.


    Ensuite, tyrtamos merci également, même si ta solution n'apporte qu'une réponse partielle aux questions que je me pose, c'est déjà une très bonne piste qui me permet de partir sur autre chose. Sinon bien plus que l'affichage c'est surtout l'écriture qui me pose problème.

    D'ailleurs j'ai testé ton code et étant donné qu'il correspond à ce que je recherchais (mais pour des tableaux) je vais tenter de l'adapter pour des dictionnaires en faisant une fonction qui récupèrera un dictionnaire en argument au lieu d'un tableau.

    J'y retourne

  9. #9
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    J'ai donné un code d'affichage pour une liste parce que ça correspondait à ton exemple de départ, mais on peut afficher n'importe quel objet python de base, y compris des dictionnaires, et j'ai un tuto pour cela:

    http://python.jpvweb.com/mesrecettes....php?id=printx

    A noter que pour afficher des objets complexes comme des arbres (des listes de listes de listes...), la fonction de parcours de l'objet est récursive.

    Sinon pour les encodages, une bonne pratique avec Python v2.x est de travailler au maximum en unicode, et de faire les conversions au plus tôt dans les entrées et au plus tard dans les sorties. Avec les lectures-écritures disques, on utilise dans ce cas le module codecs.


    Tyrtamos

  10. #10
    Membre confirmé Avatar de Mysti¢
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    155
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 155
    Par défaut
    Bonsoir,

    Le module printx m'a effectivement permis de solutionner mon problème, avec un simple appel de la méthode formatx() sur la chaine de caractères que je souhaitais écrire dans mon ficher de sortie. Un grand merci pour votre aide ainsi que pour vos explications sur les différentes versions de Python et leur gestion de l'encodage

  11. #11
    Membre averti
    Inscrit en
    Mai 2007
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 14
    Par défaut
    Bonjour,

    je vois bien que vous avez donné une excellente pour afficher un caractère spécial.

    mais je permets de poser la question suivante:
    comment faire pour chercher un caractère spécial dans une chaine .
    car par exemple, j'ai tenté de compter le nombre d'occurrence de la lettre 'é' dans la chaine y ça m'a affiché " 0 "
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    nbr = y .count('é')
    print nbr
    résultat:

  12. #12
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    (Attention: ce qui suit concerne Python 2.x)

    Pour que ça marche, il faut être sûr que la chaine et le caractère sont bien écrits dans le même encodage, car le 'é' n'est pas encodé de la même façon.

    Voilà un exemple qui ne marche pas:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    # x est encodée cp850 = encodage de la console DOS de Windows
    x = u"abcéèçàôùé".encode('cp850')
     
    # car est encodé cp1252 = encodage par défaut de Windows
    car = u"é".encode('cp1252')
     
    print x.count(car)
    0
    On pourrait corriger en ramenant tout en, par exemple, cp1252:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    # x est encodée cp850 = encodage de la console DOS de Windows
    x = u"abcéèçàôùé".encode('cp850')
     
    # on corrige x pour qu'il passe de cp850 à cp1252
    x = x.decode('cp850').encode('cp1252')
     
    # car est encodé cp1252 = encodage par défaut de Windows
    car = u"é".encode('cp1252')
     
    print x.count(car)
    2
    A noter que pour passer d'un encodage non-unicode à un autre encodage non-unicode, on passe toutjours par unicode!


    La solution la plus pratique est: on travaille toujours en unicode. On convertit tout ce qui rentre en unicode le plus vite possible. On convertit tout ce qui sort dans l'encodage objectif le plus tard possible.

    Dans ce cas en unicode:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    # x est encodée en unicode
    x = u"abcéèçàôùé"
     
    # car est encodé en unicode
    car = u"é"
     
    print x.count(car)
    2
    A noter que la chaine précédé de 'u' est en unicode, mais il faut dire à Python dans quel encodage se trouve la page de code avec, par exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    # -*- coding: utf-8 -*-
    et il faut utiliser un éditeur de texte qui édite et sauvegarde dans cet encodage.

    Tyrtamos

  13. #13
    Membre averti
    Inscrit en
    Mai 2007
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 14
    Par défaut
    Merci Bien,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    # x est encodée en unicode
    x = u"abcéèçàôùé"
     
    # car est encodé en unicode
    car = u"é"
     
    print x.count(car)
    2
    ça été le problème qui m'a bloqué.

    l'essentiel c'est de retenir deux règles:
    - pour savoir si une chaine est incluse dans une autre, il faut qu'elles soient toutes les deux en même encodage.

    - pour encoder une chaine non-Unicode vers l'Unicode, il faut l'encodée en Unicode d'abord.

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

Discussions similaires

  1. Réponses: 15
    Dernier message: 04/01/2007, 08h47
  2. [MySQL] Problèmes avec caractères spéciaux
    Par brokengillou dans le forum PHP & Base de données
    Réponses: 1
    Dernier message: 27/04/2006, 17h02
  3. Probléme encodage caractéres spéciaux MYSQL
    Par FoxLeRenard dans le forum Installation
    Réponses: 1
    Dernier message: 20/02/2006, 12h10
  4. [SOAP] problème de caractères spéciaux
    Par ep31 dans le forum XML/XSL et SOAP
    Réponses: 3
    Dernier message: 02/12/2005, 17h43
  5. [SQL Server] problème de caractères spéciaux
    Par mbibim63 dans le forum MS SQL Server
    Réponses: 10
    Dernier message: 02/06/2005, 18h38

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