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 :

Import modules en cours de programme


Sujet :

Python

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Amateur
    Inscrit en
    Mai 2014
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Amateur

    Informations forums :
    Inscription : Mai 2014
    Messages : 3
    Points : 1
    Points
    1
    Par défaut Import modules en cours de programme
    Bonjour,

    Je réalise un petit programme en Python visant à visualiser des feuilles de personnages pour des jeux de rôles. Comme je veux pouvoirs utiliser ce programme pour plusieurs jeux différents, j'aimerais pouvoir garder l'architecture générale du programme, et personnaliser certaines classes/fonctions dans des modules dédiés, regroupés au sein de packages spécifiques au jeu.

    J'ai donc créé dans mon programme principal une fonction setRPG dont l'objectif est d'importer les modules ad-hoc.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
        def setRPG(self,RPG):
            """
            Définit le package correspondant au jeu de rôle choisit.
            Importe les modules correspondants.
            """
            if RPG == "Jeu1":
                import Jeu1.classesPerso as cPerso
            if RPG == "Jeu2":
                import Jeu2.classesPerso as cPerso
    L'idée était ensuite d'appeler les classes et fonctions en utilisant les mêmes noms :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    setRPG("Jeu1")
    Perso1 = cPerso.Personnage()
    Malheureusement, en faisant cela, le nom cPerso n'est reconnu que dans la fonction setRPG, mais plus dès que j'en sors. Le code précédent renvoie une erreur me disant que le nom "cPerso" n'est pas défini. Par contre, si j'ajoute la ligne de création du personnage à la fin de ma fonction setRPG, cela fonctionne.

    L'idée des modules me semblait naturelle pour gérer cela, mais il semble que ce ne soit pas si évident. J'ai eu beau chercher, je n'ai pas trouvé de moyen d'importer un module dans un espace de nom plus général que celui où la commande "import" est lancé.

    A votre avis, comment puis-je faire ? La solution de packages différents pour chaque jeu est-elle pertinente ?

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

    Il y a pleins de façons pour faire çà.
    cPerso est une variable comme une autre.
    Elle sera "assignée" par "import".
    Et si on veut modifier un nom "global" dans une fonction, il suffit de le déclarer global "dans la fonction".

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

  3. #3
    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
    Comme le dit wiztricks, conserver une référence de ton instance sera indispensable.

    C'est d'ailleurs ce que l'on fait dans pratiquement tous les cas.

    Ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    from mainwindow import MainWindow
     
    class Main():
        def __init__(self):
            self.ui = MainWindow()
     
    main = Main()
    est équivalent à ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    class Main():
        def __init__(self):
            from mainwindow import MainWindow
            self.ui = MainWindow()
     
    main = Main()
    C'est self.ui qui nous intéresse pour la suite pas MainWindow.

    Il s'agit bien sur d'un cas de figure classique, mais je pense que ça correspond à ton code.

  4. #4
    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
    Salut,

    Ce que je dis s'écrit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
       def setRPG(self,RPG):
            """
            Définit le package correspondant au jeu de rôle choisit.
            Importe les modules correspondants.
            """
            global cPerso
            if RPG == "Jeu1":
                import Jeu1.classesPerso as cPerso
            if RPG == "Jeu2":
                import Jeu2.classesPerso as cPerso
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    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
    Oui mais dans son exemple il est manifestement dans une classe, donc je transpose le global en self.

  6. #6
    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 VinsS Voir le message
    Oui mais dans son exemple il est manifestement dans une classe, donc je transpose le global en self.
    Et comment pourrait marcher:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Perso1 = cPerso.Personnage()
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  7. #7
    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
    Bien sur, mais c'est par simplification que:

    Citation Envoyé par Nadelf Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    setRPG("Jeu1")
    Perso1 = cPerso.Personnage()
    setRPG() est censé être dans une classe et cPerso de même.

  8. #8
    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
    çà se défend.
    laissons le PO faire son marché.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  9. #9
    Nouveau Candidat au Club
    Homme Profil pro
    Amateur
    Inscrit en
    Mai 2014
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Amateur

    Informations forums :
    Inscription : Mai 2014
    Messages : 3
    Points : 1
    Points
    1
    Par défaut
    Salut, et merci pour vos réponses !

    Je n'avais pas percuté que cPerso était une variable ! Donc en utilisant la méthode proposée par wiztricks ça fonctionne.

    Effectivement, tout cela se fait dans une classe, donc pour l'appel je ferais bien :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    self.perso1=cPerso.Personnage()
    Par contre j'ai peur de ne pas avoir compris la remarque de VinsS :
    je transpose le global en self
    Je comprends que dans ce cas il suffit de définir la variable dans l'espace de nom de l'instance de la classe, et qu'il est inutile de la définir comme globale, est-ce bien cela ? Et si oui comment faire ?

    Une autre question également:
    Je trouve ma solution d'enchainer les "if RPG == "Jeu1": ... if RPG == "Jeu2": ..." peu élégante, car si j'ajoute un nouveau jeu il faudra que je revienne modifier cette méthode. Pas très évolutif donc. J'avais plutôt pensé à un truc du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    eval("import {}.classesPerso as cPerso".format(RPG))
    avec une gestion des exceptions pour le cas où on me demande un package qui n'existe pas. Malheureusement ça ne marche pas (erreur de syntaxe).

    Une idée ?

  10. #10
    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
    Une idée ?
    Le module importlib vous permet de passer le nom du module "jeux1" en tant que chaîne de caractère.
    Plutot qu'écrire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    eval("import {}.classesPerso as cPerso".format(RPG)
    )
    on devrait pouvoir faire marcher:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cPerso = importlib.import_module(RPG)
    Ceci dit, je suis dubitatif sur la motivation:
    Je trouve ma solution d'enchainer les "if RPG == "Jeu1": ... if RPG == "Jeu2": ..." peu élégante, car si j'ajoute un nouveau jeu il faudra que je revienne modifier cette méthode. Pas très évolutif donc.
    Ce que j'en comprend c'est que vous avez un tas de jeux 1, 2, 3,...
    Ces jeux devraient pouvoir être lancés indépendamment les uns des autres.
    Ils ont un point d'entrée "main" ou équivalent.

    Quelle est la fonction de votre code?
    J'imagine bien le "lanceur": l'utilisateur choisi le jeu qu'il veut lancer dans une bibliothèque, une liste qu'on lui présente à l'écran.
    Dans ce cas, plutôt que d'interfacer lanceur et jeux via "import", pourquoi ne pas lancer le jeu via subprocess?

    Avec un module, tout dépendra des références qui restent "par ailleurs".
    "subprocess" garantit qu'une fois le jeu fini, le ménage sera automatiquement fait.

    A vous de voir.

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

  11. #11
    Nouveau Candidat au Club
    Homme Profil pro
    Amateur
    Inscrit en
    Mai 2014
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Amateur

    Informations forums :
    Inscription : Mai 2014
    Messages : 3
    Points : 1
    Points
    1
    Par défaut
    Salut,

    D'abord merci pour l'idée d'utiliser importlib, ça fonctionne impeccable.

    Pour préciser l'usage de mon programme, les jeux dont je parle sont des jeux de rôles papier, et non des jeux vidéos. L'objectif du programme est de m'aider à gérer les fiches de personnages joueurs et non joueurs (qui varient selon les jeux) plutôt que de jongler avec des feuilles papier. Je fonctionne par sessions, au moment de la création de la session je définis le jeu une fois pour toute. Par contre si je ferme une session et que j'en relance une autre, je veux pouvoir changer de jeu. C'est là que ma méthode setRPG intervient.

    Je veux donc avoir une architecture commune (fenêtre principale, menus, liste des personnages, onglets de visualisation des personnages) qui appelle le module spécifique du jeu uniquement quand nécessaire (classe de personnage, widgets de création/visualisation/édition...). L'idée étant que si je veux ajouter un jeu, j'ai le moins de boulot possible pour créer le package correspondant.

  12. #12
    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 Nadelf Voir le message
    Pour préciser l'usage de mon programme, les jeux dont je parle sont des jeux de rôles papier, et non des jeux vidéos. L'objectif du programme est de m'aider à gérer les fiches de personnages joueurs et non joueurs (qui varient selon les jeux) plutôt que de jongler avec des feuilles papier. Je fonctionne par sessions, au moment de la création de la session je définis le jeu une fois pour toute. Par contre si je ferme une session et que j'en relance une autre, je veux pouvoir changer de jeu. C'est là que ma méthode setRPG intervient.
    Vos explications ne m'éclairent guère.
    Mais ne vous prenez pas le chou à essayer de préciser: l'important reste que votre code fonctionne.

    bon courage,

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

Discussions similaires

  1. Perte en cours de programme des modules importés
    Par bourgui78 dans le forum Général Python
    Réponses: 6
    Dernier message: 08/09/2008, 15h41
  2. Cours Tutoriels Programmation Systeme en C sous Linux en Français
    Par hocine1978 dans le forum Administration système
    Réponses: 3
    Dernier message: 19/12/2006, 23h11
  3. Réponses: 8
    Dernier message: 11/09/2006, 15h39
  4. [wsad/erreur import war]Error importing module file
    Par valal dans le forum Websphere
    Réponses: 1
    Dernier message: 05/09/2006, 15h01
  5. [Tkinter] probleme sur module oscillo (cours swinnen)
    Par xavier-Pierre dans le forum Tkinter
    Réponses: 4
    Dernier message: 07/03/2006, 23h12

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