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

Langage Perl Discussion :

utilisation de package/module dynamique ?


Sujet :

Langage Perl

  1. #1
    Membre régulier
    Homme Profil pro
    Ingénieur Systèmes
    Inscrit en
    Août 2011
    Messages
    75
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Monaco

    Informations professionnelles :
    Activité : Ingénieur Systèmes
    Secteur : Finance

    Informations forums :
    Inscription : Août 2011
    Messages : 75
    Points : 87
    Points
    87
    Par défaut utilisation de package/module dynamique ?
    bonjour,

    il y a un petit principe de base que j'ai du rater sur les packages (ou les appelle-t'on modules ?)

    aujourd'hui, j'ai une boucle (je simplifie), et j'aimerais appeler un différent package (module?) suivant la valeur de la boucle.

    un truc du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    foreach my $app (@apps) {
      use machin::$app;
      my $ret = &machin::$app::sub(truc);
      print $ret . "\n";
    }
    bien évidemment ça ne fonctionne pas, je dois apparemment utiliser des "eval" pour faire fonctionner le tout (même si j'ai pas réussi).

    on me dit que ce n'est pas la bonne méthode à utiliser, quid ?
    un best practice svp ?

    globalement, suivant l'application ($app), j'aimerais utiliser des fonctions etc. différentes et les mettre dans différents modules/packages/fichiers.

    comment faire cela ?

    merci!

    cdt,

  2. #2
    Membre habitué

    Homme Profil pro
    Statisticien
    Inscrit en
    Novembre 2010
    Messages
    122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Statisticien

    Informations forums :
    Inscription : Novembre 2010
    Messages : 122
    Points : 134
    Points
    134
    Par défaut
    Pour ma part, j'ai voulu faire de même pour une gestion de plugin.
    Je fais une boucle sur tous les .pm du répertoire "plugin" et je les "use", en effet dans un "eval".
    Le résultat est assez sympathique, car je rajoutais automatiquement un menu Tk en fonction des modules trouvés, mais en effet, cela alourdissait d'autres choses, de mémoire du débugage ou des incompatiblités avec divers outils.
    J'ai abandonné mais je reste intéressé par le principe.

  3. #3
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Le plus simple serait tout de même de charger tous les modules dont tu peux avoir besoin, quitte à ne les utiliser tous, sauf s'ils sont vraiment très gros et/ou très nombreux.

    Sinon, la fonction require permet une inclusion conditionnelle. Un truc dans ce genre (non testé)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    if ($c eq "A") {
         require module_A;
    } else {
         require module_B;
    }
    Les fonction eval et do permettent aussi de faire des choses similaires, mais je ne recommanderais pas vraiment, sauf besoin particulier.

  4. #4
    Membre régulier
    Homme Profil pro
    Ingénieur Systèmes
    Inscrit en
    Août 2011
    Messages
    75
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Monaco

    Informations professionnelles :
    Activité : Ingénieur Systèmes
    Secteur : Finance

    Informations forums :
    Inscription : Août 2011
    Messages : 75
    Points : 87
    Points
    87
    Par défaut
    salut

    les charger n'est pas un soucis, j'y arrive avec un :

    my $module = "machin::$app"
    eval("use $module");

    le soucis est d'utiliser les routines des modules après.. (comment je fais ?)

    et c'est pas très pratique non plus

  5. #5
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    La manière normale, de nos jours, d'inclure un module est d'utiliser l'opérateur use :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    use my_module;
    use my_other_module qw /func1, func2, func3/;
    La première syntaxe n'importe du module que les fonctions qui sont automatiquement exportées par le module. La seconde syntaxe spécifie une liste de fonctions que l'on veut utiliser. Mais l'opérateur use est exécuté à la compilation, et ne peut donc dépendre de conditions qui ne seront connues qu'à l'exécution.

    Je pense franchement que le plus simple serait d'utiliser use pour importer inconditionnellement tous les modules dont tu peux avoir besoin (à moins qu'ils ne soient vraiment trop gros ou trop nombreux, ou qu'il y ait des dangers de collisions de noms, ce qui serait sans doute le signe d'une conception fautive).

    Mais, si tu veux vraiment faire un import conditionnel, alors il faut comprendre que:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    use my_other_module qw /func1, func2, func3/;
    est équivalent à:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    BEGIN { require my_other_module; my_other_module->import( qw /func1, func2, func3/ ); }
    L'opérateur require est moins puissant que use, mais l'avantage de require dans ton cas est qu'il n'importe les fonctions du module qu'à l'exécution, et que l'importation peut donc être rendue conditionnelle.

    Je te conseille d'éviter les deux autres opérateurs susceptibles d'importer du code dans ton programme, eval et do, car ils sont bien moins perfectionnés et exigent bien plus de travail de vérification.

    Les opérateurs use et require présentent au moins les deux avantages suivants:
    - un module n'est chargé qu'une et une seule fois, même si par exemple ton module_A et ton module_B, tous les deux appelés par ton programme, incluent tous les deux le module_C. Avec do ou eval, cela conduirait à des problèmes de redéfinition des mêmes fonctions et des warnings (et tu actives les warnings, j'espère).
    - Toute erreur de syntaxe dans le fichier inclus entraîne la mort du programme. Pas besoin de vérifier s'il y a eu un problème en consultant le contenu de la valeur de la variable $@ comme il faut impérativement le faire avec eval et do.

    Les opérateurs eval et do restent très utiles pour leurs autres usages, mais ils sont obsolètes et à éviter pour inclure du code d'un autre fichier dans le fichier courant. Les opérateurs use (préférentiellement) et accessoirement dans certains cas particuliers require sont ceux qu'il faut utiliser de nos jours.

  6. #6
    Membre régulier
    Homme Profil pro
    Ingénieur Systèmes
    Inscrit en
    Août 2011
    Messages
    75
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Monaco

    Informations professionnelles :
    Activité : Ingénieur Systèmes
    Secteur : Finance

    Informations forums :
    Inscription : Août 2011
    Messages : 75
    Points : 87
    Points
    87
    Par défaut
    merci pour l'explication complète des modules, mais cela ne répond pas à ma question originale sur le fait d'appeler un module avec une variable dans le nom (utiliser une variable pour appeler différents modules).

  7. #7
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    D'accord, je n'avais pas bien compris ce que tu voulais faire. Je n'ai jamais essayé de faire ce genre de truc et ne suis pas convaincu que ce soit une bonne idée.

    Cela dit, si c'est vraiment ce que tu veux faire, il te faut sans doute lire le fichier du module dans une variable scalaire (après avoir neutralisé la variable de séparation des enregistrements $/ afin de "gober" l'ensemble du fichier dans la variable scalaire), puis exécuter le contenu de cette variable scalaire à l'aide de l"opérateur eval. Mais, encore une fois, je n'ai pas essayé, tu devras tester.

  8. #8
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Bonjour,
    je ne sais pas si c'est une "best practice", mais j'ai aussi utilisé des techniques plus ou moins "propres" pour charger dynamiquement des modules avec des noms dynamiques.

    Je viens de tester celle-ci, qui semble fonctionner. Elle utilise le module "if" qui permet, outre le fait de disposer d'un use avec un nom dynamique, de conditionner l'utilisation du module à une certaine condition logique :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    sub mod() {
     return "Data::Dumper";
    }
     
    use if 1, mod();
    print Data::Dumper->Dump([[qw(toto titi)]],[qw(*a)]);
    Par contre, je n'ai pas réussi à définir le nom du module dans une variable, car au moment de l'évaluation de use, cette variable semble ne pas être initialisée, même si je la place dans un bloc BEGIN.
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  9. #9
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Citation Envoyé par Philou67430 Voir le message
    Par contre, je n'ai pas réussi à définir le nom du module dans une variable, car au moment de l'évaluation de use, cette variable semble ne pas être initialisée, même si je la place dans un bloc BEGIN.
    C'est probablement parce que tu as utilisé une variable lexicale (my) limitée au bloc :
    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
    #! /usr/bin/env perl
    use strict;
    use warnings;
     
    BEGIN {
        # Rien n'est défini ici (sauf les imports de strict et warnings)
    }
     
    # On doit déclarer la variable globale avant
    my $globale;
     
    BEGIN {
        my $lexicale = 5;
        $globale = 10;
     
        print $lexicale;
    }
     
    BEGIN {
        print $globale;
     
        # Ceci ne marche pas car $lexicale n'est pas défini dans ce bloc
        #print $lexicale;
    }
     
    BEGIN {
        $globale = "Data::Dumper";
    }
     
    use if 1, $globale;
     
    __DATA__
    On peut aussi utiliser une vraie variable globale (avec our) mais il n'y a pas vraiment d'avantage, sauf si vous voulez passer outre les frontière d'un module.

    --
    Jedaï

  10. #10
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Apparemment la bonne solution™ pour charger un module après la compilation est d'utiliser Module::Load qui est dans le CORE (de même que Module::Load::Conditional si on veut quelque chose de plus nuancé).

    --
    Jedaï

  11. #11
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Citation Envoyé par Jedai Voir le message
    C'est probablement parce que tu as utilisé une variable lexicale (my) limitée au bloc :
    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
    #! /usr/bin/env perl
    use strict;
    use warnings;
     
    BEGIN {
        # Rien n'est défini ici (sauf les imports de strict et warnings)
    }
     
    # On doit déclarer la variable globale avant
    my $globale;
     
    BEGIN {
        my $lexicale = 5;
        $globale = 10;
     
        print $lexicale;
    }
     
    BEGIN {
        print $globale;
     
        # Ceci ne marche pas car $lexicale n'est pas défini dans ce bloc
        #print $lexicale;
    }
     
    BEGIN {
        $globale = "Data::Dumper";
    }
     
    use if 1, $globale;
     
    __DATA__
    On peut aussi utiliser une vraie variable globale (avec our) mais il n'y a pas vraiment d'avantage, sauf si vous voulez passer outre les frontière d'un module.

    --
    Jedaï
    J'avais aussi essayé avec our, mais j'ai peut-être loupé un truc (notamment, j'ai peut-être limité la portée du our à un bloc BEGIN...).
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

Discussions similaires

  1. Réponses: 4
    Dernier message: 17/07/2009, 17h25
  2. TDM dynamique : comment utiliser le package hyperref ?
    Par Thanatos dans le forum Mise en forme
    Réponses: 6
    Dernier message: 02/04/2007, 05h22
  3. [SAX] Utilisation du package contenant org.apache.xerces.par
    Par Sphost dans le forum Eclipse Java
    Réponses: 1
    Dernier message: 17/01/2005, 11h07
  4. [CR] Utilisation des package Oracle ??
    Par sboober dans le forum SAP Crystal Reports
    Réponses: 3
    Dernier message: 06/12/2004, 07h37
  5. prob avec utilisation de package
    Par martijan dans le forum Modules
    Réponses: 13
    Dernier message: 11/07/2003, 09h37

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