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 :

J'en perd mon Latin ByteArray Antislashs et classes.!?


Sujet :

Python

  1. #1
    Membre éprouvé
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    Juin 2010
    Messages
    1 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 077
    Par défaut J'en perd mon Latin ByteArray Antislashs et classes.!?
    Non migrant vers Python 3 mais désireux de porter mon code jusqu'au standart de clavier Latin, j'ai rencontrer le problème suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    a='¹' #admettons #keyword=ALTGR + ²
    print a # ou print str(a)
    ¹
    b=[]
    b.append(a)
    b
    ['\xc2\xb9']
    Jusque la c'est bon mais dès que j'utilise ce concept maison dans une methode de classe je rencontre le problème suivant:
    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
     
    class Test () :
     
      def __init__(self) :
        self.text='¹'
     
      def duoproblemo(self) :
        for caracteres in self.text :
           print str(caracteres) #pas de problèmes
           duo_pb_array=[]
           duo_pb_array.append(caracteres)
           print duo_pb_array[0:] #ou return
     
    #A l'exécution je me trouve avec le probléme suivant:
    test=Test()
    test.duoproblemo()
    ¹
    ['\xc2']
    ['\xb9']
    Si vous avez bien suivit vous remarquerez que duo_pb_array ne contient qu'un seul element (j'en ai besoin) et en retourne 2... alors que si j' essaie d'acceder a l'attribut il retourne le premier element retouner ou le deuxieme selon son humeur et ne contient qu'un seul index qu'il retourne...
    Si l'on exécute se genre de code directement dans le shell le problème n'apparait pas.
    Je viens de tester proceduralement sa fonctionne apparament.
    Si quelqu'un sait d'ou viens le problème, je pense que c'est un coup fumant de byteArray a cause des Antislashs et de classe, il serai sympa de me faire comprendre.

    Je viens de tester ma classe exemple de çi-dessus:... Elle marche pas mais j'ai réussi le coup analogue a l'exemple dans mon vrai programme mais il retourne ce qui est annonçer dans les résultats de la classe exemple, qui marche pas je ne sais pourquoi maintenant,..

    Que python soit avec vous.
    Je tourne en Python26 sur Linux.

  2. #2
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 492
    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 492
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Avec Python 2.x, on ne peut pas travailler en utf-8. On travaille en mode strictement non-unicode (latin1, etc...) ou on travaille en unicode interne (UCS2 = un UTF-16 simplifié). L'encodage 'utf-8' a un statut intermédiaire avec Python: il n'est pas considéré comme unicode (type str), mais c'en est un quand même...

    Par contre, on peut coder des chaines en utf-8 dans la page du code, à condition de le dire en haut (# -*- coding: utf-8 -*-), mais on doit les convertir pour les utiliser.

    Voilà 3 exemples (j'utilise ici idle configuré en utf-8 pour l'affichage):

    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
    24
     
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
     
    print "x en 'latin1'"
    x = u"abcéèçàù".encode('latin1')
    for car in x:
        print car
    print "longueur de x: ", len(x)
    print
     
    print "x en 'unicode'"
    x = u"abcéèçàù"
    for car in x:
        print car
    print "longueur de x: ", len(x)
    print
     
    print "x en 'utf-8'"
    x = u"abcéèçàù".encode('utf-8')
    for car in x:
        print car
    print "longueur de x: ", len(x)
    print
    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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
     
    x en 'latin1'
    a
    b
    c
    é
    è
    ç
    à
    ù
    longueur de x:  8
     
    x en 'unicode'
    a
    b
    c
    é
    è
    ç
    à
    ù
    longueur de x:  8
     
    x en 'utf-8'
    a
    b
    c
    Ã
    ©
    Ã
    ¨
    Ã
    §
    Ã
    *
    Ã
    ¹
    longueur de x:  13
    On voit bien qu'en utf-8, le découpage de la chaine et sa longueur sont incorrectes.

    Et pour afficher une chaine située dans une liste: voir le fil: http://www.developpez.net/forums/d98...iture-fichier/

    Tyrtamos

  3. #3
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 790
    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 790
    Par défaut
    Salut,

    Tyrtamos, je ne comprends pas tes explications.
    UTF-8 est une représentation "multibytes" alors que:
    avec latin-1 est 1 lettre, 1 octet
    tout comme UCS est 1 lettre, 1 mot.

    Les défauts pris par Python 3 sont certainement plus cohérents mais la transformation d'unicode en utf-8 sera toujours multibytes.

    L'autre soucis est que je ne reproduis le problème "initial" que lorsque je fais n'importe quoi.

    '¹' n'est pas caractère ASCII.
    Le script Python doit préciser un encoding.
    Si je mets l'encoding correct (cp850 pour moi), çà fonctionne et il n'y a que le caractère (\xfb) dans la suite de bytes.

    Par contre, je récupère "\xc2\xb9" lorsque je déclare que le charset du source est utf-8 (alors qu'il est toujours cp850).
    Et dans ce cas, le nombre de bytes du litéral est 2...

    Difficile de blâmer la version de Python: on lui dit que les chaînes de caractères sont dans un charset alors qu'elles écrites dans un autre...

    Ceci dit, la propriété longueur de la forme ¹ = 1 n'est généralement vraie qu'en Unicode. Ce qui en Python 2, force à écrire le littéral ¹ sous la forme u'¹' - i.e. on ne travaille qu'avec des représentations Unicode et on fait les transformations lors des IO.

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

  4. #4
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 492
    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 492
    Billets dans le blog
    6
    Par défaut
    Bonjour wiztricks,

    Alors, explique donc ça (la chaine est encodée en utf-8, et affichée sur idle):

    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
    24
     
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
     
    x = u"abcéèçàù".encode('utf-8')
    print len(x)
    13
     
    for car in x:
        print car
     
    a
    b
    c
    Ã
    ©
    Ã
    ¨
    Ã
    §
    Ã
    *
    Ã
    ¹


    Tyrtamos

  5. #5
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 790
    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 790
    Par défaut
    Salut Tyrtamos,

    Tu ne fais que constater que la sérialisation d'une suite de mots/caractères Unicode en UTF-8 fait correspondre plusieurs octets aux caractères non ASCII.
    x = u"abcéèçàù" # x est Unicode de longueur 8
    x = u"abcéèçàù".encode('utf-8') # x est une suite de bytes de longueur 2*5+3
    Parce que 3 caractères pur ASCII // mais certains caractères sont codés sur 4 bytes...
    Un truc à faire: on met çà dans le fichier toto.py
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    # -*- coding: cp850 -*-
     
    x = u"abcéèçàù".encode('utf-8')
    Puis, on lance l'interpréteur Python:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    import io
    f = io.open('toto.py', 'r+b')
    f.read()
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  6. #6
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 492
    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 492
    Billets dans le blog
    6
    Par défaut
    Je sais tout ça, et je n'ai pas dit autre chose: je voulais simplement montrer pourquoi on ne devait pas travailler en utf-8 avec Python 2.x, en réponse à la question posée.

    Il reste que la situation de l'utf-8 est ambigüe avec cette version de Python: c'est un vrai unicode (http://fr.wikipedia.org/wiki/Unicode), mais non reconnu comme tel (type str).

    Tyrtamos

  7. #7
    Membre Expert
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Par défaut
    Bonjour tyrtamos,

    Citation Envoyé par tyrtamos Voir le message
    Il reste que la situation de l'utf-8 est ambigüe avec cette version de Python: c'est un vrai unicode (http://fr.wikipedia.org/wiki/Unicode), mais non reconnu comme tel (type str).
    Je ne vois pas ce qui rend utf-8 plus ambigu que n'importe quel autre codec (vu que c'est le terme utilisé en python). Et je ne comprends pas ce que veux dire "c'est un vrai unicode". Il permet de coder tous les points de codes unicode, mais il ne faut pas confondre le point de code avec son encodage. Il faut considérer une chaîne unicode comme un type abstrait sur lequel on ne peut pas réaliser d'entrée/sortie sans passer par un encodage (que ce soit latin1, cp850, utf-8 ou autre).

    Ce n'est pas différent en Python 3: une chaîne encodée en utf-8 n'est pas non plus de type unicode (= str en Python 3) mais est une suite de bytes.

  8. #8
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 790
    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 790
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    Il reste que la situation de l'utf-8 est ambigüe avec cette version de Python: c'est un vrai unicode (http://fr.wikipedia.org/wiki/Unicode), mais non reconnu comme tel (type str).
    Ben non ... utf-8 est une représentation sérialisée des codes (16 ou 32 bits) d'Unicode.
    Certes UTF-8 a été construit pour que la représentation puisse être "bijective". Mais u"abcéèçàù" sera traduit en 10 code 16-bits "Unicode" et représentés par 13 octets en utf-8 parce que dans ce cas particulièr, alors que la représentation des "éèçàù" demandent 2 bytes.

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

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

    @wiztricks et dividee,

    Je n'envisage pas de rentrer dans une discussion théorique sur l'Unicode. Je trouve cependant curieux que vous ne placiez pas l'utf-8 dans l'Unicode, alors qu'il est décrit dans la norme ISO/CEI 10646 (http://fr.wikipedia.org/wiki/ISO/CEI_10646), considérée comme un sous-ensemble de l'Unicode.

    Mais le vrai problème, ici, c'est que l'utf-8 est multi-octets au delà de la partie commune avec l'ASCII (0 => 127), alors qu'il est traité dans Python 2.x comme un type 'str', c'est à dire comme tous les codecs "1 caractère = 1 octet". C'est en cela qu'il y a ambigüité: ça ressemble à un codec mono-octet, mais ce n'en est pas un...

    La conséquence, c'est que les méthodes habituelles de traitement des chaines appliquées sur des chaines utf-8 conduisent à des erreurs (len(), extraction de caractère, etc...), dès qu'il y a des caractères accentués. Le fait qu'on sache POURQUOI ça ne marche pas ne change rien: il fallait simplement le DIRE pour répondre au questionneur du présent fil.

    Tyrtamos

  10. #10
    Membre éprouvé
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    Juin 2010
    Messages
    1 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 077
    Par défaut
    Merci de vous en etre donner a coeur joie sur l'encodage...
    Dites moi si je me trompe:
    Je savais déja que que utf-8 encode sur max 4 bits selon la le caractère soit 1 soit 2 soit 3 soit 4 bits.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    "Le fait qu'on sache POURQUOI ça ne marche pas ne change rien: il fallait simplement le DIRE pour répondre au questionneur du présent fil."
    Le fait est que je ne suis pas un grand ponte de l'informatique et que j'expérimente afin d'obtenir un prg capable de prendre en charge toutes les touches de nos clavier Latin si bien qu'en traitement simple (caractères convertis dans un tableau afin de réutillser dans un dico pour pouvoir les afficher après '"print") et de pouvoir les imprimer après.

    J'ai remarquer dans mes expériences que en précisant l'encodage utf-8 je rencontre le problème énoncer dans la question:
    >>>['\xc2']
    >>>['\xb9']
    comme résultat illogique de mise en tableau de '¹'.
    Je suppose que le fichier de mon prog est encoder utf-8 et pas mon interpréteur...?
    Que faut il que je fasse pour obtenir la valeur utf-8 complète comme occurence de mon tableau et non un résultat scinder.

    Le tout assaisonner d'une mécanique qui fait que procéduralement mon programme marcherai mais comme instance non...

    J'ai reposer la question plus clairement: merci d'y répondre et de vous en donner a coeur joie sur l'encodage....

    Puisque c'est le sujet je me pose une question depuis que j'ai aborder l'encodage avec python:
    Que se passe-t-il intérieurement quand on précise un encodage puisque le type par défaut est string:
    -La variable est encoder dans l'encodage préciser ?
    -Le programme est encoder dans l'encodage préciser ?
    -Le type par défaut est il remis en question, et devient il celui encoder ?
    -Autre chose ?
    Merci de m'encoder sur l'encodage...
    J'en sais un peu plus avec l'expérimentation dans mon programme: \xc2\xb9 est un double bit encodant le caractere '¹'....

  11. #11
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 790
    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 790
    Par défaut
    Citation Envoyé par Luke spywoker Voir le message
    Que se passe-t-il intérieurement quand on précise un encodage puisque le type par défaut est string:
    -La variable est encoder dans l'encodage préciser ?
    -Le programme est encoder dans l'encodage préciser ?
    -Le type par défaut est il remis en question, et devient il celui encoder ?
    -Autre chose ?
    Merci de m'encoder sur l'encodage...
    J'en sais un peu plus avec l'expérimentation dans mon programme: \xc2\xb9 est un double bit encodant le caractere '¹'....
    Ben...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    import io
    f = io.open('toto.py', 'r+b')
    f.read()
    montre comment a été 'écrit' le non-ASCII dans le script Python.
    Si on le lit 'autrement', on va l'interpréter +/- correctement en fonction de l'encoding déclaré et des codes réellement écrits.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  12. #12
    Membre Expert
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    Je trouve cependant curieux que vous ne placiez pas l'utf-8 dans l'Unicode, alors qu'il est décrit dans la norme ISO/CEI 10646 (http://fr.wikipedia.org/wiki/ISO/CEI_10646), considérée comme un sous-ensemble de l'Unicode.
    Je ne dis pas qu'utf-8 n'est pas défini dans la norme ISO, mais qu'il ne faut pas confondre les différentes couches de la norme. Une chaîne unicode ce n'est pas la même chose qu'une suite de bytes contenant la représentatin utf-8 de cette chaîne.

    Mais le vrai problème, ici, c'est que l'utf-8 est multi-octets au delà de la partie commune avec l'ASCII (0 => 127), alors qu'il est traité dans Python 2.x comme un type 'str', c'est à dire comme tous les codecs "1 caractère = 1 octet". C'est en cela qu'il y a ambigüité: ça ressemble à un codec mono-octet, mais ce n'en est pas un...
    Je suis d'accord que la situation en 2.x n'est pas idéale; il faut réaliser qu'en 2.x, un caractère ne fait pas toujours un octet. Ambigu, cela veut dire qu'il y a plusieurs façon de le comprendre, ce qui n'est pas le cas il me semble. Mais c'est vrai que cela n'est pas intuitif. Et le fait qu'il y ait une méthode encode sur le type str en Python 2.x est aberrant. Seul le type unicode devrait posséder cette méthode. De même, le type unicode ne devrait pas avoir de méthode decode. Cela n'a pas de sens et est source de confusion.

    La morale c'est que si on est confronté au problème, la seule bonne solution est de décoder la chaîne en unicode (type 'unicode' en Python 2.x) dès que possible, faire tout le traitement en unicode, et retransformer en str le plus tard possible. Le principal mérite de Python 3.x, à ce niveau, est de faciliter cette démarche et de la rendre en partie obligatoire.

    Citation Envoyé par Luke spywoker Voir le message
    Que faut il que je fasse pour obtenir la valeur utf-8 complète comme occurence de mon tableau et non un résultat scinder.
    • Convertir en unicode (méthode "decode", ou si on lit la chaîne depuis un fichier, utiliser codecs.open ou io.open en précisant un codec de manière à récupérer directement une chaîne unicode)
    • Splitter la chaîne (ou appliquer tout autre traitement) en unicode
    • reconvertir en utf-8 après (méthode "encode", ou de nouveau en utilisant codecs.open ou io.open).

    Exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    >>> s = "abcéèçàù"
    >>> len(s)
    13
    >>> ss = s.decode('utf8')
    >>> len(ss)
    8
    >>> [c.encode('utf8') for c in ss]
    ['a', 'b', 'c', '\xc3\xa9', '\xc3\xa8', '\xc3\xa7', '\xc3\xa0', '\xc3\xb9']
    Le résultat n'est correct que parce que mon éditeur/interpréteur utilise bien de l'utf8, sinon il faut changer le codec utilisé dans "s.decode".

    Le fait de déclarer un encodage en début de fichier permet à Python d'interpréter correctement les litéraux unicode comme u"abcéèçàù". Mais bien sûr il faut mettre le bon encodage, celui qui est vraiment utilisé par l'éditeur.
    Ecrire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    # -*- coding: utf8 -*-
    s = u"abcéèçàù"
    donne le même résultat que:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    s = "abcéèçàù".decode('utf8')

Discussions similaires

  1. <table> : J'y perd mon latin !
    Par zakuli dans le forum Balisage (X)HTML et validation W3C
    Réponses: 4
    Dernier message: 07/02/2009, 17h32
  2. Problème de typage: j'en perds mon latin
    Par Garulfo dans le forum Caml
    Réponses: 7
    Dernier message: 10/06/2008, 14h22
  3. getElementsByName - j'y perds mon latin !
    Par herve42 dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 17/08/2007, 21h04
  4. Réponses: 6
    Dernier message: 23/05/2005, 16h38

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