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 :

Comment r�cup�rer dans le code l'encodage de la page (ligne coding)?


Sujet :

Python

  1. #1
    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 Comment r�cup�rer dans le code l'encodage de la page (ligne coding)?
    Bonjour,

    En haut de toutes les pages de code python, je place la ligne coding classique. Et comme je travaille en utf-8, je mets:

    Cela renseigne Python sur l'encodage des chaines cod�es en dur dans la page (page �dit�e et enregistr�e avec cet encodage, bien entendu!).

    Je cherche � r�cup�rer cet encodage (ici 'utf-8') dans le code Python. Actuellement, je cr�e une variable globale qui r�p�te l'encodage, et je ne trouve pas �a �l�gant (en plus, c'est un risque d'erreur).

    Quelqu'un sait-il comment faire?

    Merci d'avance.

    Tyrtamos

  2. #2
    Membre exp�riment�
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    141
    D�tails du profil
    Informations personnelles :
    �ge : 46
    Localisation : France, Paris (�le de France)

    Informations forums :
    Inscription : Mai 2008
    Messages : 141
    Par d�faut
    Salut !

    Une regexp qui lit la ligne de l'encodage et te retourne la valeur qui va bien (pas de probl�me de lock, le code tourne depuis "spam.pyc" et parse le fichier "spam.py"... un peut tortueux, toutefois).

    Sinon, j'ai vu que les objets fichiers disposent d'un attribut encoding, mais mon premier test ne s'av�re pas concluant (ce qui ne veut pas dire que la piste n'est pas bonne, juste que je ne l'ai pas approfondie).

    Je sais aussi qu'on peut r�cup�rer l'encodage du shell (sys.stdout.encoding), mais �a m'�tonnerait que �a te serve.

  3. #3
    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.

    Merci de la r�ponse!

    Citation Envoy� par nardo47 Voir le message
    Une regexp qui lit la ligne de l'encodage et te retourne la valeur qui va bien (pas de probl�me de lock, le code tourne depuis "spam.pyc" et parse le fichier "spam.py"... un peut tortueux, toutefois).
    Ah oui, pas mal l'id�e de faire relire le code pendant son ex�cution. Mais ce n'est gu�re plus �l�gant que ma variable globale...

    Citation Envoy� par nardo47 Voir le message
    Je sais aussi qu'on peut r�cup�rer l'encodage du shell (sys.stdout.encoding), mais �a m'�tonnerait que �a te serve.
    Eh oui, contrairement � ce qu'on peut lire ici ou l� (y compris dans la FAQ), l'encodage de la console d'affichage ne renseigne pas sur l'encodage de la page du code Python.


    Je viens de trouver une id�e de solution, limit�e � la d�couverte de l'un ou l'autre des encodages courants: iso-8859-1/latin1, iso-8859-15, cp1252, cp850, utf-8. C'est adaptable � d'autres encodages � condition de trouver un caract�re qui permet la distinction. Et si le code d�clenche une exception, c'est que l'encodage ne supporte pas autre chose que l'ASCII.

    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 quelcoding():
        """Trouve l'encodage de la page contenant le script Python"""
        try:
            if "é" == u"é".encode('iso-8859-1'):
                try:
                    if "€" == u"€".encode('iso-8859-15'):
                        coding = 'iso-8859-15'
                    else:
                        coding = 'cp1252'
                except:
                    # le sigle euro n'existe pas: c'est donc l'iso-8859-1'
                    coding = 'iso-8859-1'    # idem latin1
            elif "é" == u"é".encode('cp850'):
                coding = 'cp850'
            elif "é" == u"é".encode('utf-8'):
                coding = 'utf-8'
            else:
                # Encodage de la page non trouvé
                coding =  'iso-8859-1'  # encodage arbitraire: on peut mettre autre chose!    except:
        except:
            coding = 'ASCII'    
        return coding
    Utilisation:

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
     
    coding = quelcoding()
    Exemples de r�sultat (attention: les pages doivent �tre �dit�es et enregistr�es avec le m�me encodage que celui marqu� dans la ligne de coding du d�but de la page!):

    - avec "# -*- coding: utf-8 -*-" => renvoie utf-8

    - avec "# -*- coding: cp1252 -*-" => renvoie cp1252

    - etc... (je ne l'ai pas test� dans tous les cas possibles, et il est possible qu'il y ait encore des bugs!)


    Mais bon. Je pr�f�rerais acc�der � une variable Python qui donne le m�me r�sultat...

    Je laisse le fil ouvert: j'aimerais une solution plus simple!

    Tyrtamos

  4. #4
    Membre exp�riment�
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    141
    D�tails du profil
    Informations personnelles :
    �ge : 46
    Localisation : France, Paris (�le de France)

    Informations forums :
    Inscription : Mai 2008
    Messages : 141
    Par d�faut
    Woaw !

    Toujours pas d'id�e + pr�cise, mais un conseil sur ta fonction : essaie de placer tes caract�res et tes encoding dans un dictionnaires, sur lequel tu it�reras.
    Ca devrait all�ger le code, et surtout le rendre facilement extensible (pour peu que l'on ne doive pas changer l'encha�nement des tests).
    Attention, je n'ai pas dit que c'�tait �vident ou facile !
    Cela dit, c'est vraiment un voeu pieux, �tant donn� qu'on a des exceptions � g�rer. Tu peux oublier, sauf si tu veux vraiment te prendre la t�te.

    Vu que j'ai ma casquette d'inspecteur des travaux finis, j'en profite aussi pour te faire remarquer que tu dois r��crire (le copier/coller, c'est le mal ) cette fonction dans chaque fichier que tu veux tester ainsi.
    C'eut �t� mieux d'avoir cette fonction dans un module � part, mais je ne vois pas comment faire, vu la fa�on dont la fonction est �crite.

    Troisi�me remarque du gusse qui n'en fous pas 1 mais qui critique :
    le except tout seul, c'est le mal (bis repetitae)

    Bon, je reviens sur mon id�e de regexp : il me semble que les commentaires ne sont pas conserv�s dans le fichier .pyc.
    Par contre, les docstrings sont conserv�s, il serait possible d'indiquer l'encodage la-dedans (mais c'est encore une redondance dont on se passerait bien).

    ...
    ...
    ...
    On me crie dans l'oreillette que je dis n'importe quoi sur les commentaires

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    >>> with open('spam.py', mode='w') as f:
    ...     f.write('# -*- coding: utf-8 -*-\n')
    ...     f.write('\n')
    ...     f.write('#A useless comment\n')
    ...     f.write('def myfunction(): pass\n')
    ...
    >>> import spam
    >>> import inspect
    >>> inspect.getcomments(spam.myfunction)
    'A useless comment\n'
    >>> inspect.getcomments(spam)
    '# -*- coding: utf-8 -*-\n'
    Probl�me : je ne vois pas comment passer le module en argument de la fonction getcomments depuis l'int�rieur du module. J'ai bien pens� � l'attribut __name__, mais comme cet attribut est une string, ...

    ...
    ...

    Bon, je crois que c'est foutu => lu dans le Unicode HOWTO officiel : Python looks for "coding: name" or "coding=name" in the comment.
    CQFD.

    Je crois que ta m�thode est la meilleure pour le cas qui t'int�resse.

  5. #5
    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
    Comme ton id�e du module "inspect" m'amusait, j'ai creus� un peu, ce qui m'a amen� au code suivant (oui, j'ai honte ):

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    #!/usr/bin/python
    # -*- coding:utf-8 -*-
    import sys
    import os
     
    import inspect
    nf = os.path.splitext(os.path.basename(sys.argv[0]))[0]
    exec("import " + nf)
    com = eval("inspect.getcomments(" + nf + ")")
    coding = com.split(' ')[2].split(':')[1]
    print coding
    Ce qui affiche bien l'utf-8!!! et les autres coding lorsqu'ils sont cit�s � la place.

    Mais ce qui ne marche pas, c'est que l'importation du script d�clenche une premi�re ex�cution du script lui-m�me qui s'ex�cutera donc 2 fois!!!


    Sinon, merci pour tes autres id�es:

    - la solution du dictionnaire serait ok si tous les tests �taient de 1er niveau.

    - ok pour le except tout seul =

    - etc...

    Finalement, ma solution avec la variable globale n'�tait pas si mauvaise que �a (m�me si c'est aussi)

    En r�sum�, soit quelqu'un me donne une variable cach�e de Python qui me fournit le coding, soit je continue avec ma variable globale.

    Une id�e?

    Tyrtamos

  6. #6
    Membre exp�riment�
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    141
    D�tails du profil
    Informations personnelles :
    �ge : 46
    Localisation : France, Paris (�le de France)

    Informations forums :
    Inscription : Mai 2008
    Messages : 141
    Par d�faut
    Citation Envoy� par tyrtamos Voir le message
    Comme ton id�e du module "inspect" m'amusait, j'ai creus� un peu, ce qui m'a amen� au code suivant (oui, j'ai honte ):
    Pas de quoi avoir honte, je trouve �a int�ressant comme d�marche. L'imagination n'a pas de limite...
    En prime, j'ai enfin vu un cas d'utilisation de eval que je comprends (c�d, avec un contexte).

    Citation Envoy� par tyrtamos Voir le message
    Mais ce qui ne marche pas, c'est que l'importation du script d�clenche une premi�re ex�cution du script lui-m�me qui s'ex�cutera donc 2 fois!!!
    Ca, c'est pas glop du tout. Tant pis.

    Citation Envoy� par tyrtamos Voir le message
    Finalement, ma solution avec la variable globale n'�tait pas si mauvaise que �a (m�me si c'est aussi)
    Mais finalement, la variable globale, c'est comme tout "quand il y en a 1, �a va. C'est quand il y en a beaucoup qu'il y a des probl�mes".

    Tr�ve de citations, les variables globales ne sont pas interdites. Elles existent, on peut les utiliser.
    Apr�s, c'est toujours une t�che en + en cas de modification : changer l'encoding ET la globale, pfff... l'informatique, c'est cens� automatiser les t�ches r�p�titives, pourtant.

    Remarque : placer un test dans la docstring du module permet de ne pas oublier (ou plut�t, de se faire rappeler) qu'il y a 2 choses � changer.
    C'est la meilleure soluce que j'ai, mais si quelqu'un a une autre id�e, je suis preneur aussi.

  7. #7
    Membre exp�riment�
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    141
    D�tails du profil
    Informations personnelles :
    �ge : 46
    Localisation : France, Paris (�le de France)

    Informations forums :
    Inscription : Mai 2008
    Messages : 141
    Par d�faut
    Pendant ma lecture du chapitre sur la port�e des variables dans "Learning Python", j'ai vu �a:

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
     
    sys.modules['nomdupackage']
    ce qui m'a donn� envie de faire �a:

    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
     
    # codage.py
    # -*- coding: utf-8 -*-
    # TODO: récupérer l'encodage
     
    import sys, os, inspect
     
    if __name__ != '__main__':
        module = sys.modules[__name__]
        comment = inspect.getcomments(module)
        print comment
    # fin codage.py
     
    $ python codage.py
    $ python
    >>> import codage
    # -*- coding: utf-8 -*-
    # TODO: récupérer l'encodage
    Ce qui est certes int�ressant, mais �a ne marche que quand le fichier est import�, pas quand il est ex�cut� directement. D'ailleurs, dans ce dernier cas, on est oblig� de r�cup�rer le nom de module comme tu l'as fait et en +, il n'est pas consid�r� comme charg� dans le dictionnaire sys.modules.
    Mais je trouvais ce code int�ressant.

    Pendant que j'y suis, ce chapitre sur les globales m'a permis de clarifier mon point de vue sur les globales :
    Les globales c'est le mal quand on les modifie !

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

    On peut ajouter des variables qui soient accessibles � tout le code sans �tre "globales". Voil� ci-dessous un code qui initialise tous les encodages utiles (on peut en ajouter d'autres):

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    #!/usr/bin/python
    # -*- coding:utf-8 -*-
    import sys
     
    class Cod(object):
        def __init__(self):
            self.coding = 'utf-8'  # idem ligne coding en haut de page
            self.codin = sys.stdin.encoding
            self.codout = sys.stdout.encoding
            self.codisk = sys.getfilesystemencoding()
     
    cod = Cod()
    Utilisation:

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
     
    print cod.coding
    print cod.codin
    print cod.codout
    print cod.codisk
    Ce qui, dans une console DOS de Windows donne:

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
     
    utf-8
    cp850
    cp850
    mbcs
    Un des avantages de cette solution, c'est qu'on peut instancier une autre variable avec d'autres valeurs pour coller avec un autre contexte, sans perdre pour autant ce qu'on a d�fini au d�part. On peut aussi passer facilement la variable comme param�tre d'une fonction pour transmettre d'un seul coup le contexte des encodage E/S.

    Cette solution est, bien entendu, g�n�ralisable � n'importe quelles autres variables que l'on veut accessibles � tout le code.

    Tyrtamos

  9. #9
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, r�seau, syst�me et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, H�rault (Languedoc Roussillon)

    Informations professionnelles :
    Activit� : Technicien Help Desk, maintenance, r�seau, syst�me et +
    Secteur : High Tech - �diteur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par d�faut
    Bonjour,

    Et un simple :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #!/usr/bin/python
    # -*- coding:cp850 -*-
    import sys
    import os.path
     
    f = open(os.path.join(os.getcwd(), sys.argv[0]))
    for ligne in (result for result in f if 'coding' in result):
            coding = ligne.split(' ')[2].split(':')[1]
            print coding
            f.close()
            break
    ?

    @+

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

    Ah oui, tant qu'� lire le script qui est en train de s'ex�cuter...

    Voil� la m�me en une ligne:

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    coding = [ligne for ligne in open(os.path.abspath(sys.argv[0])) if 'coding' in ligne][0].split(' ')[2].split(':')[1]
    Pour que �a marche, il ne faut pas qu'il y ait un espace entre 'coding:' et l'encodage. Sinon, il faudrait changer la formule.

    Cela suppose aussi que le code .py est l�, m�me si c'est le .pyc qui s'ex�cute.

    Et, bien s�r, l'absence de la ligne coding plante le programme.

    En l'absence d'une variable syst�me Python qui donnerait le r�sultat, c'est probablement la meilleure solution (en plus de la variable globale).

    Merci!

    Tyrtamos

  11. #11
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, r�seau, syst�me et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, H�rault (Languedoc Roussillon)

    Informations professionnelles :
    Activit� : Technicien Help Desk, maintenance, r�seau, syst�me et +
    Secteur : High Tech - �diteur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par d�faut
    Citation Envoy� par tyrtamos Voir le message
    Pour que �a marche, il ne faut pas qu'il y ait un espace entre 'coding:' et l'encodage. Sinon, il faudrait changer la formule.
    Il suffit de tester les deux cas, c'est les seuls possibles.

    Citation Envoy� par tyrtamos Voir le message
    Et, bien s�r, l'absence de la ligne coding plante le programme.
    Se limiter � la lecture de la deuxi�me ligne de code (la seule possible) �vite le plantage.

    Citation Envoy� par tyrtamos Voir le message
    Cela suppose aussi que le code .py est l�, m�me si c'est le .pyc qui s'ex�cute.
    Pas de r�ponse

    @+

Discussions similaires

  1. R�ponses: 4
    Dernier message: 13/02/2018, 14h47
  2. R�ponses: 0
    Dernier message: 20/05/2010, 17h13
  3. R�ponses: 5
    Dernier message: 08/03/2010, 14h09
  4. [VB.Net] Comment r�cup�rer dans un textbox une donn�e BDD ?
    Par zzzmoi dans le forum Acc�s aux donn�es
    R�ponses: 10
    Dernier message: 08/07/2007, 02h08
  5. R�ponses: 2
    Dernier message: 11/12/2006, 12h38

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