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 :

Le satané encoding UTF8


Sujet :

Python

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Septembre 2013
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 10
    Points : 7
    Points
    7
    Par défaut Le satané encoding UTF8
    Bonjour à tous
    Voila mon problème

    Je récupère une variable titre (dans laquelle j'ai des car. accentués), je l'encode en UTF8 (et je la colle dans un fichier txt en utf8 lui aussi, soit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fichier.write(titre.encode('utf8')+'\n')
    Quand je la ressorts sous forme de liste dont je decode chaque element, soit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    fichier = open("titres", "r")
        loldtitre = fichier.readlines()
        loldtitre = [line.decode('utf8') for line in loldtitre]
    quand je "print loldtitre" j'obtiens toujours des caractères \xe9 genre "Les donn\xe9es\n"

    Je précise que mon fichier commence par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #!/usr/bin/python
    # -*- coding: utf8 -*-
    ...je perds des cheveux une bonne ame pour me dire comment avoir enfin "Les données\n" (il y a un \n car retour charriot dans la ligne)

  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,

    Il faut voir ce que tu fais exactement et tenir compte du fait que l'affichage dans la console peut varier.

    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
     
    Python 2.7.3 (default, Feb 27 2014, 20:00:17) 
    [GCC 4.6.3] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> l = u"Les akènes de Ficus pumila sont utilisés à Taïwan et à Singapour comme ingrédient de base de la gelée de Aiyu,\nune spécialité culinaire,\ninventée au XIXe siècle, que l'on consomme habituellement glacée et citronnée."
    >>> with open("test", "w") as f:
    ...     f.write(l.encode("utf8"))
    ... 
    >>> with open("test", "r") as f:
    ...     t = f.readlines()
    ... 
    >>> tt = [i.decode("utf8", "replace") for i in t]
    >>> tt
    [u'Les ak\xe8nes de Ficus pumila sont utilis\xe9s \xe0 Ta\xefwan et \xe0 Singapour comme ingr\xe9dient de base de la gel\xe9e de Aiyu,\n', u'une sp\xe9cialit\xe9 culinaire,\n', u"invent\xe9e au XIXe si\xe8cle, que l'on consomme habituellement glac\xe9e et citronn\xe9e."]
    >>> tt[0]
    u'Les ak\xe8nes de Ficus pumila sont utilis\xe9s \xe0 Ta\xefwan et \xe0 Singapour comme ingr\xe9dient de base de la gel\xe9e de Aiyu,\n'
    >>> print tt[0]
    Les akènes de Ficus pumila sont utilisés à Taïwan et à Singapour comme ingrédient de base de la gelée de Aiyu,
     
    >>>

  3. #3
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    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 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Je suppose qu'il s'agit de Python 2, et tout ce qui dit ci-dessous concerne Python 2 (ce problème a évolué fortement avec Python 3).

    Ces problèmes d'encodage sous Python 2 sont faciles à résoudre une fois qu'on en a compris les particularités, et qu'on s'est donné de bonnes méthodes de travail.

    1- la ligne "# -*- coding: utf-8 -*-" ne dit pas à Python qu'il doit travailler en utf-8 mais simplement que les chaines codées en dur dans la page de code sont encodées en utf-8. Il faut, bien sûr que ce soit vrai, c'est à dire que cette page de code a bien été enregistrée en "utf-8" par l'éditeur de texte qui a été utilisé pour l'écrire.

    2- pendant l'exécution du programme, toutes les chaines sur lesquelles on travaille sont en unicode. A noter qu'il est dangereux de travailler en interne en utf-8 puisque les caractères ne prendront pas tous le même nombre d'octets: len("e") => 1 mais len("é") => 2.

    3- Les chaines qu'on rentre dans le programme sont converties en unicode le plus tôt possible. Cela nécessite de connaître l'encodage de la chaine source selon le périphérique.

    4- les chaines qu'on sort du programme sont converties dans le bon encodage le plus tard possible. Cela nécessite de connaître l'encodage de la chaine destination selon le périphérique. Attention: les chaines intégrées dans une liste (un tuple, un dictionnaire, ...) ne sont pas correctement affichées par print en Python 2!. Par exemple, dans une console en utf-8 et avec des chaines en utf-8:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    print "données", ["données"]
    données ['donn\xc3\xa9es']
    Quelques exemples:

    Au titre du point 3: entrées des chaines dans le programme:

    - chaines codées en dur: on utilise u"..." pour que la chaine soit convertie en unicode dès la lecture par l'interpréteur

    - chaines issues d'un fichier et encodées en "utf-8" (par exemple): on utilise le module codecs:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    import codecs
    with codecs.open("monfichier", "r", "utf-8") as f:
        maliste = [chaine.rstrip() for chaine in f]
    - chaines issues d'une saisie dans une console en utf-8: x = raw_input("=>").decode("utf-8")

    - idem mais console en cp850 (console cmd.exe de Windows): x = raw_input("=>").decode("cp850")

    - chaines issues d'une saisie dans n'importe quelle console: x = raw_input("=>").decode(sys.stdin.encoding). Sauf dans certaines consoles d'outils de développement qui renvoient None à sys.stdin.encoding.


    Au titre du point 4: sortie des chaines du programme:

    - chaines destinées à un fichier en "utf-8" (par exemple): on utilise le module codecs:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    import codecs 
    with codecs.open("monfichier", "w", "utf-8") as f:
        for chaine in maliste:  # => maliste est une liste de chaines unicode
            f.write(chaine + u"\n")
    - chaines unicode destinées à un affichage demandant l'utf-8 (linux): print machaine.encode("utf-8")

    - chaines unicode destinées à un affichage demandant l'encodage "cp850" (console cmd.exe de Windows): print machaine.encode("cp850")

    - chaines unicode destinées à un affichage dans n'importe quelle console: print machaine.encode(sys.stdout.encoding). Sauf dans certains outils de développement qui renvoient None pour sys.stdout.encoding.

    - liste de chaines unicode à afficher avec print: on peut utiliser une fonction qui transforme la liste en chaine:

    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
    23
    def chliste(x):
        """ prend une données qui peut être une chaine unicode ou une liste de 
            chaines unicode
            retourne une chaine unicode pour affichage
        """
     
        # traitement des chaines unicode
        if isinstance(x, unicode):
            return u'"%s"' % x
     
        # traitement des listes
        elif isinstance(x, list):
            L = u"["
            if x!=[]:
                L += u"%s" % chliste(x[0])
                for elem in x[1:]:
                    L += u", %s" % chliste(elem)
            L += u"]"
            return L
     
        # si x n'est ni liste ni chaine (int, long, float): on convertit en chaine
        else:
            return u"%s" % (x)
    Cette fonction renvoie une chaine de caractère unicode, qu'on peut, bien entendu, convertir ensuite dans n'importe quel encodage.

    Si on voulait afficher d'autres objets Python type tuple ou dictionnaire, (set, etc...) et même un mélange de ces objets, il faudrait étendre cette fonction selon le même principe.

    Cette fonction étant récursive, la liste à afficher peut avoir n'importe quelle profondeur:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    print chliste([u"éèçàùôï", [u"éèçàùôï", [u"éèçàùôï", u"éèçàùôï", [u"éèçàùôï", ]]], u"éèçàùôï", u"éèçàùôï", ]).encode(u"utf-8")
    ["éèçàùôï", ["éèçàùôï", ["éèçàùôï", "éèçàùôï", ["éèçàùôï"]]], "éèçàùôï", "éèçàùôï"]
    Bon courage!
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  4. #4
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    - chaines codées en dur: on utilise u"..." pour que la chaine soit convertie en unicode dès la lecture par l'interpréteur
    Bonjour

    Cela peut-il aider de rajouter la ligne from __future__ import unicode_literals dans le source ???
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  5. #5
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Cela peut-il aider de rajouter la ligne from __future__ import unicode_literals dans le source ???
    unicode_literals est une des options pour porter un code Python3 vers Python2.
    Vous pouvez trouver ici un laïus sur avantages/inconvénients.
    Mais comment organiser son code pour supporter les encodings, i.e. appliquer les conseils rappelés par Tyrtamos me semble être un pré-requis pour comprendre quand utiliser ou pas ce __future__.

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

Discussions similaires

  1. [Encodage] base64 encode utf8
    Par istiti dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 19/12/2012, 11h42
  2. Réponses: 4
    Dernier message: 27/07/2012, 23h55
  3. Problème d'encoding UTF8
    Par hugo123 dans le forum Servlets/JSP
    Réponses: 1
    Dernier message: 03/08/2009, 16h19
  4. Problème Encoding UTF8 en client serveur
    Par warmy dans le forum C#
    Réponses: 0
    Dernier message: 16/06/2009, 02h23
  5. Client encoding UTF8
    Par the java lover dans le forum PostgreSQL
    Réponses: 5
    Dernier message: 08/09/2008, 10h03

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