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 :

Propager des options au travers de modules et packages


Sujet :

Python

  1. #1
    Membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 10
    Par défaut Propager des options au travers de modules et packages
    Bonjour à tous,

    Je cherche une manière propre de propager des options de configuration au travers de plusieurs modules et packages. Par exemple des options de debug ou autres qui vont influencer la dynamique du programme.

    L'approche que j'utilisait était un module config qui contenant des variables globales. Cette approche marche tant que les options sont "statiques", cela se complique quand on veut les rendre "dynamiques" avec une CLI par exemple : il faut faire un import avant chaque requête à ce module sinon les changements effectués par d'autres modules ne sont pas visibles.

    Une solution ?

    Merci.

  2. #2
    Membre émérite
    Homme Profil pro
    heu...
    Inscrit en
    Octobre 2007
    Messages
    648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : heu...

    Informations forums :
    Inscription : Octobre 2007
    Messages : 648
    Par défaut
    Utiliser shelve ?

  3. #3
    Membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 10
    Par défaut
    Citation Envoyé par N.tox Voir le message
    Utiliser shelve ?
    Je trouve assez lourd de devoir utiliser un fichier pour connaitre les options passés à mon programme.

    Edit: De plus cette configuration est non persistante.

  4. #4
    Membre émérite
    Homme Profil pro
    heu...
    Inscrit en
    Octobre 2007
    Messages
    648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : heu...

    Informations forums :
    Inscription : Octobre 2007
    Messages : 648
    Par défaut
    En fait après un rapide test, des variable mises dans un module importé par d'autres, peuvent être dynamiquement modifiées :
    module cmn.py:
    module a.py
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    import cmn
     
    def double():
        cmn.ze_var *= 2
     
    def print_():
        print cmn.ze_var
    module b.py:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    import cmn
     
    def quart():
        cmn.ze_var /= 4
     
    def print_():
        print cmn.ze_var
    module test.py:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    import a
    import b
     
    a.print_()
    a.double()
    b.print_()
    b.quart()
    a.print_()
    print 'import'
    import cmn
    print cmn.ze_var
    a.print_()
    input()

    l’exécution du script test.py me donne ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    10
    20
    5
    import
    5
    5

  5. #5
    Membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 10
    Par défaut
    Cela marche bien, cependant ça ne marche plus quand on a des packages.

    Structure du test:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    base/__init__.py
    base/cmn.py
    base/test.py
    base/child/__init__.py
    base/child/test.py
    les fichiers __init__.py sont vides.

    Le fichier base/cmn.py :
    le fichier base/test.py :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    import cmn
    import child.test as t
     
    cmn.ze_var = 15
     
    print cmn.ze_var
    t.print_()
    print cmn.ze_var
    le fichier base/child/test.py
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    from base import cmn
     
    def print_():
        print cmn.ze_var
    Une fois la variable d'environnement PYTHONPATH mise à jour avec le répertoire courant, l'exécution de python base/test.py produit le résultat suivant:

  6. #6
    Membre émérite
    Homme Profil pro
    heu...
    Inscrit en
    Octobre 2007
    Messages
    648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : heu...

    Informations forums :
    Inscription : Octobre 2007
    Messages : 648
    Par défaut
    Tu n'as pas besoin d'ajouter le package dans le python path pour que les imports intra-package s'effectuent.
    Tiens, tu devrais trouver cela intéressant.
    Néanmoins, cela ne résoudra pas ton pb pour autant... utiliser un serveur local ?

  7. #7
    Membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 10
    Par défaut
    Citation Envoyé par N.tox Voir le message
    Tu n'as pas besoin d'ajouter le package dans le python path pour que les imports intra-package s'effectuent.
    Tiens, tu devrais trouver cela intéressant.
    Néanmoins, cela ne résoudra pas ton pb pour autant... utiliser un serveur local ?
    J'évite d'utiliser les imports relatifs, je trouve la notation absolue plus intuitive et plus simple à maintenir. Mais c'est plus une question de gout. Je conçois très bien que cela peut poser problème lorsqu'on décide de déplacer le package...

    Revenons à nous moutons, baaaaaaah, pour l'instant j'ai décidé de passer par shelve, comme tu m'as suggéré dans ton premier message. Je trouve ça dommage de passer par un fichier, mais cette approche a le mérite de marcher. Tant que je ne trouve pas mieux je vais utiliser cette solution.

    Le topic n'est donc pas clos j'attends toujours des propositions

  8. #8
    Membre émérite
    Homme Profil pro
    heu...
    Inscrit en
    Octobre 2007
    Messages
    648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : heu...

    Informations forums :
    Inscription : Octobre 2007
    Messages : 648
    Par défaut
    Hmmm... si t'es sous linux, tu peux créer un hardlink de base/cmn.py dans /base/child/
    Je n'ai aucune idée de la viabilité de cette proposition

  9. #9
    Membre Expert
    Inscrit en
    Août 2010
    Messages
    1 124
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 1 124
    Par défaut
    Pour ma part j'utilise des attributs de classe
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    class options:
        debug= True
        parametre= 1
    Mais pour éviter les imports cycliques, je suis la plupart du temps obligé de placer cette classe dans un fichier séparé genre config.py, du coup j'ai les mêmes problèmes que toi.

    Cela dit, passer par une classe plutot que par le module lui même permet plus de flexibilité (p.ex: décoration de la classe d'options pour aller chercher les valeurs dans un fichier)

  10. #10
    Membre émérite
    Homme Profil pro
    Inscrit en
    Décembre 2007
    Messages
    758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 758
    Par défaut
    salut,

    s'il s'agit de configuration pourquoi ne pas utiliser ConfigParser ? et de rendre l'instance de configuration disponible depuis tous tes modules (via import ou passage explicite en argument)

  11. #11
    Membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 10
    Par défaut
    Citation Envoyé par kango Voir le message
    salut,

    s'il s'agit de configuration pourquoi ne pas utiliser ConfigParser ? et de rendre l'instance de configuration disponible depuis tous tes modules (via import ou passage explicite en argument)
    J'utilise argparse pour récupérer les arguments, c'est le fait de rendre des données disponibles depuis tous les modules qui est problématique à partir du moment où on a des sous packages (cf. plus haut). Pour ce qui est du passage explicite, c'est ce que je veux éviter à tout prix.

  12. #12
    Membre émérite
    Homme Profil pro
    Inscrit en
    Décembre 2007
    Messages
    758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 758
    Par défaut
    ok, tu as les options de configurations depuis la ligne de commande, je pensais qu'elles venait depuis un fichier.

    personnellement, je m'inspirerai de l'approche du module logging de python.

    celui contient un logger qui est un singleton que l'on configure du module que l'ont veut, et que l'on appelle du module que l'on veut (en passant par un import logging).

    cela revient à utiliser les approches exposées ci dessus mais de partager un objet (aussi simple ou complexe que tu le désires) en lieu et place de variable chaines ou entières.

  13. #13
    Membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 10
    Par défaut
    Avec un singleton le résultat sera le même qu' ici.

    Le fait est que lorsqu'on parle de modules tout va bien mais lorsqu'on parle de packages cela se complique...

  14. #14
    Membre émérite
    Homme Profil pro
    Inscrit en
    Décembre 2007
    Messages
    758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 758
    Par défaut
    le cas que tu mentionnes ne fonctionne pas uniquement parce que la variable globale est non mutable (dans ton cas un integer)

    on peut simuler le comportement indépendamment des modules, packages, etc...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    a = 1
    b = a
    b = 2
    print a
    print b

  15. #15
    Membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 10
    Par défaut
    Citation Envoyé par kango Voir le message
    le cas que tu mentionnes ne fonctionne pas uniquement parce que la variable globale est non mutable (dans ton cas un integer)

    on peut simuler le comportement indépendamment des modules, packages, etc...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    a = 1
    b = a
    b = 2
    print a
    print b
    Non.

    Voici un exemple qui met en évidence le même comportement avec un singleton (sources ici).

    Structure du test:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    base/__init__.py
    base/cmn.py
    base/test.py
    base/child/__init__.py
    base/child/test.py
    Les fichiers __init__.py sont vides.

    Le fichier base/cmn.py :
    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
    class ConfigMgr(object):
        __instance__ = None
     
        def __init__(self):
            self.__class__.__instance__ = self
            self.d = {}
     
        @classmethod
        def instance(cls):
            if not cls.__instance__:
                ConfigMgr()
                assert(cls.__instance__)
            return cls.__instance__
     
    def set(**kwargs):
        instance = ConfigMgr.instance()
        for (name, value) in kwargs.iteritems():
            instance.d[name] = value
        print "  dictionnaire apres set : ", ConfigMgr.instance().d
     
    def get(name):
        instance = ConfigMgr.instance()
        print "  dictionnaire juste avant get : ", ConfigMgr.instance().d
        return instance.d[name]
    Le fichier base/test.py :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    import cmn
    import child.test as t
     
    cmn.set(truc='blabla')
    print
    print cmn.get('truc'), ' (dans base.test)'
    print
    try:
        t.print_()
    except KeyError as ke:
        print "KeyError: ", ke
    print
    print cmn.get('truc'), ' (dans base.test)'
    print
    Le fichier base/child/test.py
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    from base import cmn
     
    def print_():
        print 'base.child.test.print_'
        print cmn.get('truc')
    Sortie sur la console lorsqu'on exécute base/test.py:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
      dictionnaire apres set :  {'truc': 'blabla'}
     
      dictionnaire juste avant get :  {'truc': 'blabla'}
    blabla  (dans base.test)
     
    base.child.test.print_
      dictionnaire juste avant get :  {}
    KeyError:  'truc'
     
      dictionnaire juste avant get :  {'truc': 'blabla'}
    blabla  (dans base.test)

  16. #16
    Membre émérite
    Homme Profil pro
    Inscrit en
    Décembre 2007
    Messages
    758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 758
    Par défaut
    salut,

    j'ai récupéré ton code source. j'ai exécuté les commandes suivantes (en interactif).

    (j'ai juste ajouté un id pour vérifier que l'on a la même instance à chaque fois et c'est le cas)

    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
    >>> import base
    >>> import base.test
      dictionnaire apres set :  {'truc': 'blabla'}
      id :  140602658422224
     
      dictionnaire juste avant get :  {'truc': 'blabla'}
      id :  140602658422224
    blabla  (dans base.test)
     
    base.child.test.print_
      dictionnaire juste avant get :  {'truc': 'blabla'}
      id :  140602658422224
    blabla
     
      dictionnaire juste avant get :  {'truc': 'blabla'}
      id :  140602658422224
    blabla  (dans base.test)
    du coup, c'est le comportement que tu souhaites il me semble non ?

    tu dois probablement lancer le script base/test.py sans avoir importer base. (ce qui chez moi crash car base/child/test.py me retourne un import error du module base à moins que je configure PYTHONPATH de sorte que le module base soit trouvé et dans ce cas j'ai la même exception:

    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
    python base/test.py
    id cnm:  139737530170008
      dictionnaire apres set :  {'truc': 'blabla'}
      id :  139737530145680
     
      dictionnaire juste avant get :  {'truc': 'blabla'}
      id :  139737530145680
    blabla  (dans base.test)
     
    base.child.test.print_
    id cnm: 139737530170848
      dictionnaire juste avant get :  {}
      id :  139737530146320
    KeyError:  'truc'
     
      dictionnaire juste avant get :  {'truc': 'blabla'}
      id :  139737530145680
    blabla  (dans base.test)
    mais du coup, comme tu peux le voir, tu as deux instances de ConfigMgr

    cela est dû au fait que le module cnm est importé deux fois (voir le id du module cmn):

    - une fois par l'intermédiaire de base/test.py qui a cnm.py dans le même répertoire
    - uen fois par base/child/test.py qui importe cnm via base et la variable PYTHONPATH.

    du coup ton Singleton n'en n'est plus un mais c'est lié au fait que le module n'est pas un Singleton non plus.

    exécuter un script depuis l'intérieur d'un package sans avoir importer le package racine peut conduire à des problèmes. Mais celui là, je l'avais jamais vu ;p

    le problème initial est bien lié à la nature immuable des variables globales utilisées et ce dernier problème est lié au fait que tu as deux instances de configuration différentes à cause du soucis d'import.

  17. #17
    Membre Expert
    Inscrit en
    Août 2010
    Messages
    1 124
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 1 124
    Par défaut @kango
    Comment peut-on créer un module ou package qui soit un singleton ? (ou un Borg).

  18. #18
    Membre émérite
    Homme Profil pro
    Inscrit en
    Décembre 2007
    Messages
    758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 758
    Par défaut
    un module est un singleton. le cas de ce post est quand même très particulier

  19. #19
    Membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 10
    Par défaut
    Donc faire un import base avant chaque import base.cmn résoudrait mon problème ?

  20. #20
    Membre émérite
    Homme Profil pro
    Inscrit en
    Décembre 2007
    Messages
    758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 758
    Par défaut
    pas tout à fait. en fait, il vaut mieux selon moi ne pas lancer un script directement depuis l’intérieur d'un package python (on perd les imports relatifs).

    c'est une constatation personnelle donc très certainement pas universelle. je construis toujours les scripts au même niveau que le package racine.

    par exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    ton_script_1.py
    ton_script_2.py
    base
    `---- __init__.py
    chaque script faisant un:

    ou


+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Propagation des données à travers un tjavaRow
    Par Juwan dans le forum Développement de jobs
    Réponses: 4
    Dernier message: 03/05/2012, 14h09
  2. Charger un module automatiquement avec des options debian
    Par ZiMo dans le forum Administration système
    Réponses: 4
    Dernier message: 22/12/2005, 14h22
  3. Stocker des options
    Par koolkris dans le forum API, COM et SDKs
    Réponses: 6
    Dernier message: 11/02/2005, 16h00
  4. [Preferences] Stockage des options
    Par Yan83 dans le forum Eclipse Platform
    Réponses: 1
    Dernier message: 03/05/2004, 10h38
  5. Parametrage des options de projet
    Par ares7 dans le forum EDI
    Réponses: 7
    Dernier message: 22/07/2002, 15h33

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