creative commons
Perles de Mongueurs : détection de modules
icone programmation
Signature :
GNU/Linux Magazine
Sommaire de l'article :

Retrouvez cet article dans : Linux Magazine 98

Depuis le numéro 59, les Mongueurs de Perl vous proposent tous les mois de découvrir les scripts jetables qu’ils ont pu coder ou découvrir dans leur utilisation quotidienne de Perl. Bref, des choses trop courtes pour en faire un article, mais suffisamment intéressantes pour mériter d’être publiées. Ce sont les perles de Mongueurs.

 

Détecter la disponibilité de modules à l’exécution

Pour utiliser des modules externes en Perl, il y a le classique use. Le problème est que, si le module n’existe pas, le programme ne sera même pas compilé. Il y a pourtant des cas où le module n’est nécessaire que pour une fonctionnalité optionnelle du programme. Celui-ci fonctionnera alors dans un mode dégradé, mais il faut pouvoir détecter que l’on est dans ce cas pour effectuer les opérations nécessaires (comme griser un élément dans une interface graphique). Il faut donc, pendant l’exécution, détecter si un module est présent ou non pour savoir qu’il faut désactiver certaines parties (ou faire n’importe quel autre traitement). Cela peut principalement être fait de deux manières.

La méthode manuelle

Quand on parle de déplacer un problème de la phase de compilation à celle d’exécution, on pense normalement à eval. Ce mot-clé peut être utilisé de deux manières, en le faisant suivre par un bloc ou par une chaîne. La version avec bloc ne permet pas de contourner ce qui nous intéresse ici, car son contenu est compilé en même temps que tout le reste. On va donc utiliser la version avec une chaîne qui contiendra un bout de code Perl qui ne sera compilé qu’au moment de l’exécution. Si un problème survient pendant la compilation de ce qui est passé à eval, la variable $@ contiendra une description de ce problème. Dans le cas contraire, elle sera vide. On peut alors facilement tester la présence d’un module de cette manière :

 

    eval "use Module::A::Tester";
    if ($@)
    {
        # Code à exécuter si le module est absent
    }
    else
    {
        # Ici tout va bien
    }
Dans le else, on peut aussi tester le numéro de version en regardant la variable $Module::A::Tester::VERSION. On peut également utiliser un bloc eval avec require plutôt que use de cette manière :
    eval {
        require Module::A::Tester;
        import Module::A::Tester;
    };
Cela marchera comme précédemment, si ce n’est que le nom du module ne peut être déterminé à l’exécution, car le comportement de require est d’alors considérer cela comme un nom de fichier et non pas de module. Il faudrait alors utiliser le module Module::Util avec sa fonction module_path pour convertir le nom du module. On peut mettre tout ceci dans une fonction qui prendra en entrée un nom de module et un numéro de version facultatif. Elle retournera une valeur vraie si le module est disponible, une valeur fausse sinon. Un petit exemple suit la définition de la fonction. Il affichera Module Présent ou Module Absent selon les cas.
    sub checkModule
    {
        my ($module, $version) = @_;
        eval "use $module $version";
        return 0 if $@;
        return 1;
    }    print ‘Module ‘ .
        (checkModule(‘HTML::Parser’, 3.55) ?
        ‘Présent’ : ‘Absent’) ."\n";
Son fonctionnement est assez simple. On essaye d’abord de charger le module avec eval. Si on a une erreur, pas besoin d’aller plus loin et on retourne 0. Si on a passé cette phase, le module est bien disponible. On va alors immédiatement retourner que tout va bien si le numéro de version n’est pas spécifié. Sinon, on teste qu’il est bien plus grand que la valeur en entrée. Cette méthode n’est utile que si on utilise réellement le module ensuite et non pas seulement pour tester sa présence. En effet, les éventuels blocs BEGIN présents seront exécutés.

La méthode avec un module CPAN

Il existe un module CPAN qui permet de faire à peu près la même chose. Comme la plupart des modules déjà existants, il a été plus testé et gère plus de cas que la simple fonction précédente. Ce module est UNIVERSAL::require. Son utilisation crée une fonction require qui s’utilise dans un style objet. Pour reprendre l’exemple précédent :
    use UNIVERSAL::require;    my $module = ‘HTML::Parser’;

print ‘Module ‘ .
        (($module->require(3.55)) ?
        ‘Présent’ : ‘Absent’) ."\n";
Le message d’erreur de chargement, si require a renvoyé une valeur fausse, est présent dans $@ ou dans $UNIVERSAL::require::ERROR. Par rapport à un use, ceci n’aura pas appelé la fonction import() du module. Il faudra donc éventuellement l’appeler ensuite explicitement, si require s’est bien passé, comme ceci :
    $module->use;
Un module équivalent s’appelle Module::Load::Conditional avec la fonction can_load(). On lui passe en paramètre une référence vers un hash qui contient la liste des modules à tester comme clés et les numéros de versions pour les valeurs ou undef pour ne pas la vérifier. L’exemple précédent devient alors :
    use Module::Load::Conditional qw(can_load);
    my $modulesATester = {
            ‘HTML::Parser’ => 3.55    };

print ‘Module ‘ .
        (can_load(modules => $modulesATester) ?
        ‘Présent’ : ‘Absent’) ."\n";
On aurait pu indiquer plusieurs modules dans $modulesATester. La fonction renvoie une valeur vraie seulement si tous les modules ont pu être chargés avec succès.

À vous !

Envoyez vos perles à perles@mongueurs.net. Elles seront peut-être publiées dans un prochain numéro de GNU/Linux Magazine.

Retrouvez cet article dans : Linux Magazine 98

Il y a : 0 commentaire(s)

Donnez votre avis

Vous devez avoir ouvert une session pour écrire un commentaire.

Brèves
Édito : Linux Pratique Essentiel N°24
Édito : Linux Pratique HS N°23
Édito : GNU/Linux Magazine 146
Édito : GNU/Linux Magazine HS N°58
Édito : Open Silicium N°5
Communication
Linux Pratique HS 23 – Communiqué de presse
Linux Pratique Essentiel N°24 – Communiqué de presse
Gnu/Linux Magazine sponsor et partenaire de PROLOGIN
Linux Essentiel partenaire des Rencontres du Libre de Lion sur Mer (Normandie)
GNU/Linux Magazine HS 58 – Communiqué de presse
prochainement moteur de recherches des articles
 
:
:
Jours heures minutes secondes
En kiosque
Le tout nouveau Linux Pratique Essentiel est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...

Le tout nouveau Linux Pratique est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...

Le tout nouveau GNU/Linux Magazine est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...

Le tout nouveau GNU/Linux Magazine HS est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...

Le tout nouveau Open Silicium est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...

Le tout nouveau Linux Pratique est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...

Le tout nouveau Misc est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...

Le tout nouveau GNU/Linux Magazine est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...