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èmes de codage (encore)


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Rédacteur/Modérateur

    Avatar de Jiyuu
    Homme Profil pro
    Développeur amateur
    Inscrit en
    Janvier 2007
    Messages
    2 456
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur amateur
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 2 456
    Billets dans le blog
    15
    Par défaut Problèmes de codage (encore)
    Bonjour à tous,

    Et oui encore un post concernant un problème de codage.
    Je suis sur le PC depuis 8h ce matin et je pense que cela a du me lobotomiser un peu le cerveau.

    Je demande donc un petit coup de main et d'oeil neuf sur le problème suivant.

    Je récupère le contenu d'1 wx.TextCtrl multiligne et souhaite l'afficher dans le un document pdf grâce à Reportlab.

    Dans le contenu de ce wxTextCtrl j'ai évidemment des accents.

    Malgré un grand nombre d'essai je ne parviens pas à éviter le message d'erreur suivant:

    Elements.append(p(u'%s'%com, font('courier', 11, 0, 0)))
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xe9 in position 44: ordinal not in range(128)
    voici les différents essais que j'ai pu faire... ou txt est mon wx.TextCtrl
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    !-*- conding:utf-8 -*-
    com = txt.GetValue()
    Elements.append(p(u'%s'%com, font('courier', 11, 0, 0)))
    ### ou
    com = txt.GetValue()
    Elements.append(p(com, font('courier', 11, 0, 0)))
    ### ou
    com = txt.GetValue()
    if not wx.USE_UNICODE:
    com = com.encode("iso8859-15", "replace")
    Elements.append(p(com, font('courier', 11, 0, 0)))
    ### ou
    com = txt.GetValue()
    com = com.encode("cp1252", "replace")
    Elements.append(p(com, font('courier', 11, 0, 0)))
    ### ou
    ...[/CODE]

    Le plus affolant et ce qui me fait complètement tourner la carte (expression de chez moi qui veut dire) c'est que ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    !-*- conding:utf-8 -*-
    com = 'éééééé'
    Elements.append(p(com, font('courier', 11, 0, 0)))
    ça fonctionne nikel...

    J'attends grandement une aide de votre part et aussi... une énième explication.

    merci de votre patience
    Initiation à Qt Quick et QML : Partie 1 - Partie 2
    En cas de besoin, pensez à la
    Mon site et mes tutoriaux sur Developpez.com
    Pas de question technique par MP... Les forums sont là pour ça

  2. #2
    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,

    Sans prétendre maitriser le sujet, je vais essayer d'apporter quelques éléments de réponse. A force de me "cogner" à ce sujet, j'ai fini par trouver quelques recettes qui ont l'air de marcher.

    Mais je ne connais pas suffisamment wx pour savoir en quel encodage il travaille. En tout cas, si tu ne sais pas non plus, il faut chercher, car Python ne devine pas tout. Dans ton premier exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Elements.append(p(u'%s'%com, font('courier', 11, 0, 0)))
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xe9 in position 44: ordinal not in range(128)
    Le 'u' que tu as utilisé oblige Python à convertir la chaine en unicode interne, mais comme tu ne donnes pas l'encodage de cette chaine, il prend par défaut le codec ASCII qui ne supporte pas les caractères accentués. Donc, convertis explicitement ta chaine en unicode avec decode(), en donnant son encodage d'origine. Si c'est l'utf-8, cela donne: com.decode('utf-8')

    - Dans tous les cas, quand Python donne une erreur d'encodage avec le codec ASCII, ça veut dire qu'on l'oblige à faire une conversion sans lui donner les éléments.

    - Ta ligne de coding est bizarre: la bonne ligne est:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    # -*- coding:utf-8 -*-
    - Quand on définit une telle ligne, cela suppose que le code source est édité et enregistré avec le même encodage. En cas de doute, vérifie avec un éditeur hexa les octets de ton fichier sur disque. En fait, la ligne coding sert à dire à Python quel est l'encodage du code source, et donc des chaines stockées en dur dans celui-ci. Contrairement à ce qu'on lit ici ou là, ce n'est pas l'encodage par défaut de l'interpréteur (qui se configure différemment), et ça n'a aucun rapport avec l'encodage de la console de sortie (sys.stdout.encoding).

    - Quand dans le code source, une chaine a été définie avec un 'u' devant, elle est transformée en unicode pendant l'exécution, en utilisant bien entendu le coding. En fait, les 2 lignes suivantes sont équivalentes (avec le coding à utf-8), et convertissent toutes les 2 la chaine x (initialement stockée en 'utf-8' dans le fichier source), en unicode interne:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    x = u"abcéèçàù"
    x = "abcéèçàù".decode('utf-8')
    - Quand Python parle d'unicode, il parle d'unicode interne et non de n'importe quel unicode! D'après ce que j'ai pu lire ici ou là, ce serait, dans la plupart des implantations de Python, de l'UCS2 qui est une version simplifiée de l'UTF-16 (simplifiée au sens que l'UCS2 a toujours 2 octets, ce qui n'est pas le cas de l'UTF-16). Mais pour Python, une chaine en utf-8 n'est pas en unicode mais en str: type(u"abcéèçàù")=unicode, mais type(u"abcéèçàù".encode('utf-8'))=str.

    - Il est très important de considérer que seul l'unicode interne permet de manipuler les chaines en interne. Pour en être convaincu, il suffit de se livrer à ce petit test:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    x = u"abcéèçàù"  # chaine en unicode interne
    print len(x)
    8
     
    x = u"abcéèçàù".encode('utf-8')  # chaine en utf-8
    print len(x)
    13
    Dans cet exemple, Python s'est trompé sur le nombre de caractères de la chaine utf-8.

    - Une fois qu'on a compris ça, on adopte la logique de codage suivante:

    1- il faut convertir le plus tôt possible toutes les chaines entrantes en unicode interne (entrées code source, lecture disque, saisie console, ...)

    2- if faut convertir le plus tard possible toutes les chaines sortantes dans l'encodage voulu (affichage console, écriture disque, ...)

    3- entre les 2, il ne faut travailler qu'en unicode.

    - Pour convertir une chaine d'un encodage à un autre, on passe toujours par l'unicode interne!
    => Pour passer de n'importe quel encodage à l'unicode interne, on utilise decode(encodage_de_la_chaine_à_convertir).
    => Pour passer de l'unicode interne à n'importe quel encodage, on utilise encode(encodage_voulu).

    Dans tes autres exemples, tu cherches à convertir ta chaine com en unicode interne avec encode(), alors que ça devrait être avec decode().

    Regarde si ta méthode font() n'a pas une option encoding.

    Je ne sais pas ce que ta fonction p() est censée faire, mais c'est elle qui semble déclencher le besoin de conversion: à voir de plus près.

    Voilà ce que je peux dire du sujet pour l'instant. J'espère que ça t'éclaire un peu.

    Tyrtamos

  3. #3
    Rédacteur/Modérateur

    Avatar de Jiyuu
    Homme Profil pro
    Développeur amateur
    Inscrit en
    Janvier 2007
    Messages
    2 456
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur amateur
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 2 456
    Billets dans le blog
    15
    Par défaut
    Bonjour et déjà merci pour toutes ces explications.

    J'ai pas encore tout pigé et je pense qu'une bonne relecture au calme un peu plus tard devrait arranger ceci.

    J'ai cependant quelques petites remarques:
    1°) Concernant ma première ligne du script, effectivement je suis allez un peu vite lors de l'écriture et celle qu'il y a dans mon code est bien celle que tu me donnes.

    2°) Concernant le , celui-ci ne m'a pas permis de résoudre mon problème (il m'a même retourner la même erreur qu'avec "ascii"), j'ai donc fouillé encore et encore sur le net et j'ai testé tout ce que je trouvais... au final un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    com.decode(''iso8859-1")
    à l'air de convenir.

    3°) Dans mon code p est défini ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    import reportlab.platypus as rpb
    p = rpb.Paragraph
    celle-ci permet de traiter un texte de "x" caractères avec retour à la ligne, ...
    Après quelques recherches et essais, voici ce que j'ai pu avoir comme message d'erreur:
    if type(text) is str: text = text.decode('utf8')
    File "C:\python25\lib\encodings\utf_8.py", line 16, in decode
    return codecs.utf_8_decode(input, errors, True)
    UnicodeDecodeError: 'utf8' codec can't decode byte 0xe9 in position 0: unexpected end of data
    Ce "if" fait partie du script Paragraph.py, ce qui explique effectivement mon souci.
    J'ai donc dans ce script remplacé cette fonction par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if type(text) is str: 
        try: text = text.decode('utf8')
        except: text = text.decode("iso8859-1")
    et à priori ça marche pas mal.

    Merci encore pour ton aide.

    Bye.

    Jiyuu

    PS: dois-je informer les big boss de reportlab de ma petite modif???

    [EDIT]
    Je viens de faire un essai avec ces caractères:
    é à è ê ï€ @
    le seul qui ne convient pas est €... Celui-ci ressort sous forme d'un carré noir...
    Initiation à Qt Quick et QML : Partie 1 - Partie 2
    En cas de besoin, pensez à la
    Mon site et mes tutoriaux sur Developpez.com
    Pas de question technique par MP... Les forums sont là pour ça

  4. #4
    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
    Citation Envoyé par Jiyuu Voir le message
    le seul qui ne convient pas est €... Celui-ci ressort sous forme d'un carré noir...
    Si tu travailles en iso8859-1, c'est normal. Pour avoir le sigle euro, il faut l'iso8859-15.

    Tyrtamos

  5. #5
    Rédacteur/Modérateur

    Avatar de Jiyuu
    Homme Profil pro
    Développeur amateur
    Inscrit en
    Janvier 2007
    Messages
    2 456
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur amateur
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 2 456
    Billets dans le blog
    15
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    Si tu travailles en iso8859-1, c'est normal. Pour avoir le sigle euro, il faut l'iso8859-15.

    Tyrtamos
    J'ai fait la modif mais à priori ça ne fonctionne pas mieux...

    Je rencontre un autre petit souci plus important que celui-ci (qui ne rentre pas vraiment dans le cadre de ce topic, mais tu pourras peut être m'aider)...

    Comme je l'ai dit plus haut, j'utilise
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    import reportlab.platypus as rpb
    p = rpb.Paragraph
    pour générer des paragraphes dans mon document pdf.
    Le souci c'est que reportlab.platypus.Paragraph gère les sauts de lignes comme un espace et du coup la mise en page obtenue n'est pas vraiment celle souhaitée.

    Une solution assez simple serait de détecter chaque saut de ligne avant d'utiliser reportlab.platypus.Paragraph et de gérer les éléments qu'il y aura entre chaque comme des paragraphes indépendants...

    Vois-tu comment je pourrais faire pour détecter ces sauts?
    Initiation à Qt Quick et QML : Partie 1 - Partie 2
    En cas de besoin, pensez à la
    Mon site et mes tutoriaux sur Developpez.com
    Pas de question technique par MP... Les forums sont là pour ça

  6. #6
    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
    S'il s'agit de détecter les caractères de fin de ligne '\r' et/ou '\n', ça me parait facile et je ne te vois pas poser ce genre de question (mais attention cependant à l'unicode).

    Donc, ça doit être: à quel endroit de la ligne je dois générer un changement de ligne, compte tenu de la police utilisée et de la longueur de l'affichage.

    Si c'est bien ta question: je ne sais pas. Si c'est autre chose, précise!

    Tyrtamos

  7. #7
    Expert confirmé
    Avatar de Guigui_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2002
    Messages
    1 864
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2002
    Messages : 1 864
    Par défaut
    J'ai exactement le même besoin que toi. J'utilise wxPython et Reportlab pour me faire un pdf.

    Ma version de wxPython est la version unicode (donc tout ce que je récupère des TextCtrl est de l'unicode)

    J'ai également des TextCtrl multiligne. Voici ce que je fais. Je n'ai jamais eu (pour le moment) de problème avec mes caractères (en même temps, je ne suis jamais allé trop loin au niveau du test des caractères unicode).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    c= reportlab.pdfgen.canvas.Canvas("toto.pdf")
    mm = reportlab.lib.units.cm / 10.
    mystyle = reportlab.lib.styles.getSampleStyleSheet()['Normal']
    mystyle.fontSize = 10
    mystyle.alignment = reportlab.lib.enums.TA_JUSTIFY
    frame = reportlab.platypus.Frame(0, 151*mm, 95*mm, 124*mm, leftPadding=1, bottomPadding=1, rightPadding=1, topPadding=1, id=None, showBoundary=0)            
    p = []
    for i in MyTextCtrl.GetValue().split("\n"):
        p.append(reportlab.platypus.Paragraph(i, mystyle))
    frame.addFromList(p, c)

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

Discussions similaires

  1. Problème de session (encore)
    Par akapando dans le forum Langage
    Réponses: 2
    Dernier message: 23/05/2006, 16h54
  2. Problème de codage de caractères depuis l'import
    Par compu dans le forum SQL Procédural
    Réponses: 1
    Dernier message: 22/03/2006, 08h37
  3. Réponses: 3
    Dernier message: 22/03/2005, 09h13
  4. Réponses: 9
    Dernier message: 04/03/2005, 13h58
  5. [Accents - XML] Problème de codage non supporté !!
    Par Smortex dans le forum Composants VCL
    Réponses: 6
    Dernier message: 24/11/2002, 11h00

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