SELFHTML/Aides à la navigation CGI/Perl Modules Perl |
En programmant, vous vous rendrez vite compte que vous avez toujours besoin de certaines tâches routinières . Les fichiers doivent toujours être lus et relus, dans un environnement CGI, les formulaires doivent toujours être exploités, Pour la communication avec d'autres ordinateurs sur Internet, il faut toujours établir une interface de connexion Internet etc... Maintenant, l'interpréteur Perl Internet dispose bien déjà d'une quantité de fonctions, qui maîtrisent ce genre de tâches routinières. Néanmoins plus le nombre de ces fonctions intégrées à l'interpréteur Perl est élevé, plus l'interpréteur sera volumineux, lent et gourmand en ressources. C'est pourquoi il existe un deuxième type de fonctions, à savoir celles qui ne sont pas intégrées directement dans l'interpréteur mais qui sont disponibles sous la forme de scripts Perl. Ces scripts Perl spéciaux sont appelés modules. Les modules disposent de fonctions (mais aussi de variables) pour certaines tâches routinières. Pour pouvoir utiliser ces fonctions dans vos propres scripts Perl, incorporez simplement les modules dans lesquelles se trouvent les fonctions souhaitées. Ensuite, vous pouvez accéder aux fonctions et variables des modules.
Entre-temps il y a des milliers de modules Perl qui sont disponibles gratuitement. Il n'y a plus guère un domaine de programmation pour lequel il n'existe pas déjà des modules avec des fonctions performantes toutes prêtes. Les modules sont mis à la disposition du public par des programmeurs zélés et compétents sur Internet. Quelques uns de ces modules se font concurrence, et au cours du temps, celui des modules qui est le meilleur dans la pratique s'impose. Naturellement, il existe aussi des modules qui sont utilisés plus souvent que d'autres. Ce dernier point a conduit à distinguer aujourd'hui deux classes importantes de modules disponibles au public: Il existe les modules standard et les modules CPAN. Les modules standard sont ceux qui sont livrés avec l'interpréteur Perl, et les modules CPAN sont disponibles sur Internet pour être téléchargés. Les modules standard sont de ce fait naturellement beaucoup plus répandus. Étant donné qu'à chaque installation typique de l'interpréteur Perl, ils sont aussi installés, ils peuvent également être utilisés presque aussi tranquillement que les fonctions intégrées à Perl. Car même quand un script Perl est transféré sur un autre ordinateur pour y faire son travail, les mêmes modules y sont disponibles - à la condition qu'une version actuelle correspondante de l'interpréteur Perl y soit installée. Si par contre cous téléchargez des modules CPAN que vous incorporez dans vos propres scripts, le transfert d'un script sur un autre ordinateur n'est pas vraiment sans problèmes. Car le script n'y fonctionnera qu'après que les mêmes modules CPAN y sont installés.
Dans ce chapitre, vous trouverez une partie sur les modules standard de Perl et une partie sur les modules CPAN. Vous y trouverez une vue d'ensemble des modules dont vous disposez.
Par ailleurs, il va de soi qu'il est également possible d'écrire ses propres modules. Pour des scripts Perl importants, il est aussi préférable de répartir le code de telle façon qu'il n'y ait plus qu'un script principal mince qui comporte des modules incorporés pour les différentes tâches. Supposons que vous programmiez un script Perl qui traite un fichier avec une certaine structure de données. Vous pouvez très bien pour ce travail écrire un module qui contienne toutes les fonctions pour lire le fichier et le copier dans des variables appropriées et pour écrire dans le fichier les données après traitement. Vous pouvez ensuite simplement incorporer ce module dans le script principal et accéder à ses fonctions et à ses variables. S'il fallait ensuite par exemple modifier le format de fichier du fichier de données, seul le module doit être remanié alors que le script principal et les autres modules éventuels n'en sont pas affectés. Vous trouverez des exemples typiques de modules propres au projet dans la partie sur la programmation orientée sur l'objet. Ce n'est pas fortuit. Car le travail orienté sur les modules et la programmation orientée sur l'objet, dans le style moderne, sont étroitement liés chez Perl.
Les modules Perl sont donc (la plupart du temps) eux mêmes des scripts Perl. Il s'agit toutefois de scripts pour lesquels certaines règles et particularités sont à respecter, ce qui est abordé dans le détail par la suite.
Pour l'incorporation de modules, Perl dispose des fonctions use et require. En général, il est recommandé aujourd'hui d'utiliser la fonction use
parce qu'elle respecte mieux l'esprit des modules. En utilisant use
le module est incorporé dès le commencement du script qui l'incorpore. Il est donc à disposition avant même que la première ligne de code du script principal ne soit exécutée. En utilisant require
l'autre fichier par contre n'est incorporé qu'à l'endroit ou figure l'instruction require
. Avant l'appel correspondant, les fonctions ou variables du module ne sont donc pas disponibles et eu cas par exemple où l'appel de require
est placé dans l'embranchement d'une instruction conditionnelle, il ne sera exécuté que si le script aboutit dans l'embranchement correspondant. Un exemple doit illustrer ceci.
#!/usr/bin/perl -w print "Ici se manifeste le module \"moduletest.pm\"\n"; 1; |
#!/usr/bin/perl -w print "Ici se manifeste le script principal\n"; require ;moduletest; |
#!/usr/bin/perl -w print "Ici se manifeste le script principal\n"; use moduletest; |
La première partie de l'exemple montre le code du fichier moduletest.pm. Les parties de l'exemple 2a et 2b montrent chacune un script Perl dans lequel ce fichier module est incorporé. Dans le script test_require.pl (2a) le module est incorporé avec require
, dans le script test_use.pl (2b) par contre il l'est avec use
. Les deux scripts (2a et 2b) sont identiques mise à part la différence dans l'appel de la fonction. Le résultat de la sortie est cependant différent. Dans le 2a (donc pour l'incorporation du module avec require
il donne:
Ici se manifeste le script principal
Ici se manifeste le module "moduletest.pm"
En 2b par contre (incorporation du module avec use
) la sortie donne:
Ici se manifeste le module "moduletest.pm"
Ici se manifeste le script principal
La raison en est qu'un module incorporé avec use
est exécuté avant que le code du script dans lequel il est incorporé ne soit exécuté. Pour require
le script incorporé est par contre exécuté à l'endroit où il est incorporé.
À première vue, cette différence plaide plutôt pour l'emploi de require
et moins pour celui de use
. Dans la pratique pourtant il en est ainsi, la plupart du temps, que les fichiers modules ne contiennent pas directement de code exécutable mais sont constitués de fonctions (sous-programmes) qui peuvent ensuite être appelées dans le script qui les incorpore.
#!/usr/bin/perl -w sub Modulprint { print "Ici se manifeste le module \"moduletest.pm\"\n"; } 1; |
#!/usr/bin/perl -w print "Ici se manifeste le script principal\n"; require moduletest; Modulprint(); |
#!/usr/bin/perl -w print "Ici se manifeste le script principal\n"; use moduletest; Modulprint(); |
Dans cet exemple les scripts 2a et 2b génèrent la même sortie, à savoir:
Ici se manifeste le script principal
Ici se manifeste le module "moduletest.pm"
La raison en est que le code du module figure maintenant dans un sous-programme nommé Modulprint
. Dans les scripts qui l'incorporent test_require.pl et test_use.pl l'instruction Modulprint();
appelle la fonction correspondante du module incorporé.
Une autre différence importante entre use
et require
est que vous pouvez mentionner exactement avec use
quels noms de fonctions et de variables exactement, vous voulez importer d'un module alors que require
n'offre pas cette possibilité. De plus amples renseignements 'à ce sujet plus bas dans la partie Utilisation étendue de use (@EXPORT, @EXPORT_OK et qw).
Les fichiers modules peuvent être sauvegardés dans un des répertoires définis dans la variable prédéfinie @INC
ou dans un sous-répertoire de ceux-ci. Lors d'une installation typique de Perl, la liste @INC
contient une série de sous-répertoires du répertoire d'installation de Perl ainsi que le répertoire actuel, à savoir la plupart du temps le répertoire dans lequel le script principal incorporant le fichier module se trouve.
La sauvegarde de fichiers modules dans le répertoire ou dans un sous-répertoire du script principal est indiquée quand les fichiers modules ne sont utilisés par aucun autre script. Quand les fichiers modules contiennent du code écrit de façon suffisamment générale pour que vous puissiez les utiliser pour différents scripts, il est alors préférable de sauvegarder les fichiers modules dans un des autres répertoires nommés dans @INC
.
Pour décider où vous pouvez sauvegarder vos fichiers modules, il vous faut d'abord connaître la liste des répertoires autorisés. Le script Perl tout simple suivant peut vous y aider.
#!/usr/bin/perl -w print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Répertoires de modules permis</title>\n"; print "</head><body>\n"; print "<h1>Répertoires pour la sauvegarde de fichiers modules:</h1>\n"; foreach (@INC) { print "<tt>$_</tt><br>\n"; } print "</body></html>\n"; |
Le script sort simplement le contenu de la liste @INC
ligne par ligne en code HTML. Si vous sauvegardez ce code comme fichier pl dans le répertoire CGI et l'appelez dans le navigateur, tous les chemins de répertoires disponibles sont affichés. Dans la configuration habituelle, le dernier élément de la liste est un point seul (.
). Il figure pour "répertoire actuel" et obtient que l'interpréteur Perl, après avoir recherché en vain un fichier incorporé dans les chemins de répertoires généraux, recherche dans le répertoire actuel.
Au cas où vous ne vouliez sauvegarder votre fichier module dans aucun des répertoires proposés par @INC
, vous pouvez aussi le sauvegarder ailleurs. Vous devez alors il est vrai, avant d'incorporer un tel fichier module, ajouter le chemin du répertoire où se trouve le fichier module à la liste @INC
.
#!/usr/bin/perl -w use lib "/httpd/docs/cgi-shared/special"; use lib "/httpd/docs/cgi-shared/module"; print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Répertoires de modules permis</title>\n"; print "</head><body>\n"; print "<h1>Répertoires pour la sauvegarde de fichiers modules:</h1>\n"; foreach (@INC) { print "<tt>$_</tt><br>\n"; } print "</body></html>\n"; |
Par une instruction telle que use lib
suivie de la mention d'un chemin de répertoire, ce chemin est ajouté au début de la liste @INC
. Le script en exemple est le même script CGI que celui pour la sortie des chemins contenus dans @INC
qui précède. Dans le cas présent, il montre que les chemins personnels ainsi définis ont été pris en considération dans la liste.
Les modules peuvent être sauvegardés dans un des répertoires de @INC
ou dans un de leurs sous-répertoires. De cette règle sont tirées des formes possibles d'adressage d'un module lors de l'incorporation avec use
ou require
.
require "statistiques.pm"; require statistiques; use "statistiques.pm"; use statistiques; |
Les quatre exemples montrent l'incorporation d'un module sauvegardé dans un fichier nommé statistiques.pm
. Le fichier se trouve directement dans un des répertoires disponibles dans la liste @INC
comme Emplacement de sauvegarde des modules et de la liste @INC possible. Les mêmes règles s'appliquent pour require
et use
. Soit vous notez le nom de fichier complet du fichier module entre guillemets (les fichiers modules doivent avoir l'extension .pm
), soit vous notez le nom de fichier sans l'extension .pm
et sans guillemets.
Quand le fichier se trouve dans un sous-répertoire de l'un des répertoires de @INC
, la mention de chemin relative est indispensable.
require "modules_calcul/statistiques.pm"; require modules_calcul::statistiques; use "modules_calcul/statistiques.pm"; use modules_calcul::statistiques; |
Les quatre exemples montrent à nouveau l'incorporation d'un module statistiques.pm
. Le fichier se trouve dans un sous-répertoire nommé modules_calcul
de l'un des répertoires de @INC
. Dans ce cas il est vrai, la syntaxe sans guillemets est à privilégier. Car lorsque vous travaillez avec des guillemets, il vous faut adresser le fichier à incorporer avec le nom "complet". La syntaxe sans guillemets se satisfait par contre du nom sans extension .pm. Le fichier module incorporé doit avoir cette extension. La chaîne de caractères qui symbolise les séparateurs de répertoires, donc les hiérarchies est constituée par deux fois deux points (::
).
Quelque soit la simplicité apparente du concept des modules en Perl - il présente cependant quelques problèmes. Supposons que vous définissiez dans votre propre Script Perl un sous-programme nommé get_data()
. Dans le même script, vous incorporez un module dont le code contient également la définition d'un sous-programme nommé get_data()
. Afin que l'interpréteur Perl sache à l'appel de get_data()
, laquelle des deux fonctions est concernée, il doit avoir une possibilité de lui faire savoir quelle fonction est appelée.
À cette fin il existe en Perl le concept des espaces de nommage. Chaque espace de nommage représente ce qu'on appelle un Package (anglais pour paquet). Chaque script Perl dans lequel vous ne faites aucune mention particulière de l'espace de nommage (du package) concerné, utilise un package par défaut. il porte le nom main
.
#!/usr/bin/perl -w $texte_sorti = "Hello ancien monde. "; print $texte_sorti; package nouveau_monde; $texte_sorti = "Hello nouveau monde. "; print $texte_sorti; package main; print $texte_sorti; |
L'exemple illustre l'espace de nommage par défaut nommé main
. Tout d'abord une scalaire nommée $texte_sorti
est définie et se voit affecter une valeur. Cette valeur est sortie tout de suite après. Étant donné qu'à cet instant précis de l'exécution de script, aucune autre mention concernant l'espace de nommage n'a été faite, le script se trouve toujours dans l'espace de nommage par défaut main
. Dans la deuxième étape, un nouvel espace de nommage en propre nommé nouveau_monde
est défini à l'aide de la fonction package. Dans celui-ci une scalaire nommée $texte_sorti
est à nouveau définie cette fois-ci avec une autre valeur. Cette nouvelle valeur est elle aussi sortie.
À cet instant précis de l'exécution de script deux scalaires nommées $texte_sorti
existent - à savoir celle du nouveau_monde
et celle du package par défaut main
. Pour le contrôle dans l'exemple, il est à nouveau "commuté" sur le package main
. Pour ce faire, c'est à nouveau la fonction package
qui est appelée, mais cette fois avec le nom par défaut main
. Des deux scalaires de ce nom existantes, c'est maintenant celle qui a été définie en premier dans le script qui est sortie, donc celle qui fait partie de l'espace de nommage par défaut main
. La toute dernière commande print
sort donc à nouveau Hello ancien monde.
.
Comme le montre l'exemple, l'espace de nommage peut donc être changé à souhait à l'intérieur d'un script. Ce qui permet d'atteindre un très haut degré de souplesse. Les modules en Perl profitent de cette souplesse. Un module peut à vrai dire par l'application de la technique des packages héberger par exemple plusieurs classes (d'objet) dans un fichier module ou bien élargir d'autres modules (qui sont eux aussi constitués de packages), même si la technique, il faut l'avouer n'est pas des plus propres. Un exemple simple doit illustrer ce contexte.
$texte_module = "Ceci est le contenu de la scalaire \$texte_module\n"; package moduletest; $texte = "Ceci est le contenu de la scalaire \$texte\n"; 1; |
#!/usr/bin/perl -w use moduletest; print $texte_module; print $moduletest::texte; |
La première partie de l'exemple est le script module, la deuxième partie le script principal. Le script module reçoit dans l'exemple le nom moduletest.pm et est incorporé dans le script principal avec l'instruction use moduletest;
.
Le fichier module commence par la définition d'une scalaire nommée $texte_module
. Étant donné qu'auparavant aucun autre package n'est appelé, le package actif est celui dans lequel le module est incorporé. Tout ce qui est défini dans cet espace de nommage, se trouve ainsi dans l'espace de nommage main
du script qui l'incorpore. Dans l'exemple, le script qui l'incorpore, donc le script principal sort dans son espace de nommage par défaut main
avec print $texte_module;
simplement la variable qui a été définie dans l'espace de nommage main
du fichier module. $texte_module
a été donc définie directement dans l'espace de nommage par défaut du script qui incorpore. Le package main
a donc été élargi par le module.
Dans le script module, donc dans Modul.pm, un nouvel espace de nommage est cependant défini avec package
plus loin dans le déroulement du script. Il porte le même nom que le fichier module sans extension, à savoir moduletest
. Dans le script principal qui incorpore le fichier module, il ne peut être accédé aux variables et fonctions définies dans le package moduletest
, qu'en mentionnant l'espace de nommage correspondant. L'instruction print $moduletest::texte;
indique comment il est accédé à l'autre package. Le nom d'une variable ou d'une fonction est précédé du nom du package et de deux fois deux points (::
). Les scalaires, listes et hashes commencent toujours par leurs signes caractéristiques $
, @
et %
. Entre celui-ci et le nom de variable figure cependant le nom de package et les deux fois deux points.
L'adressage de variables ou fonctions dans d'autres packages et modules avec nom de package::nom de variable/fonction
n'est pas possible si les variables ou fonctions sont déclarées avec my. C'est pourquoi l'application de my
est aussi recommandée dans la pratique pour obtenir un cantonnement bien propre de variables ou fonctions au seul package ou module où elle ont un rôle à jouer.
Étant donné que les modules eux-mêmes peuvent incorporer d'autres modules et que des modules distincts doivent représenter des îlots de données, la technique d'élargissement de packages trouve à un moment ou à un autre ses limites. Pour permettre de fixer des interfaces "publiques" de modules, vous avez la possibilité de rendre visibles des symboles distincts (donc des noms de variables ou des noms de fonction par exemple) dans les deux packages (à savoir celui qui incorpore et celui qui est incorporé). Vous pouvez exporter les symboles du module ou les importer dans le script ou module qui les incorpore.
Un module peut pour cette raison vous forcer à mentionner exactement, lors de l'incorporation quelles variables et fonctions vous désirez importer dans l'espace de nommage du script qui incorpore. Pour ce faire, il existe ce qu'on appelle le module d'exportation (Exporter-Modul), un module standard de Perl. Ce module attend dans le module incorporé deux listes nommées @EXPORT
et @EXPORT_OK
. Un module peut incorporer le module d'exportation et remplir ces deux listes avec les noms de variables et de fonctions qui peuvent être principalement exportés dans un script qui incorpore. Dans le script qui incorpore vous pouvez à nouveau mentionner quels noms exportables du module vous désirez importer dans l'espace de nommage de votre script.
package moduletest; require Exporter; @ISA = qw(Exporter); @EXPORT = qw(%CHAMPS_FORMULAIRE); @EXPORT_OK = qw($pointeuse @donnees_log recherche_client); # ici vient le code du module ... # dans le code ontrouve entre autres: # un hash nommé %CHAMPS_FORMULAIRE # une scalaire nommée $pointeuse # une liste nommée @donnees_log # une fonction nommée recherche_client 1; |
#!/usr/bin/perl -w use moduletest qw($pointeuse); # ici vient le code du script ... |
Le fichier module incorpore lui même dans l'exemple un module, à savoir le module standard Exporter
avec require. L'instruction @ISA = qw(Exporter)
définit la classe Exporter
comme classe de base de la classe actuelle, représenté par le package actuel (dans l'exemple donc moduletest
). Ce faisant, la méthode import
, qui est définie dans le module ou plutôt la classe Exporter
, est transmise en héritage à la classe moduletest
. Ces explications qui peuvent paraître un peu compliquées sont dictées par l'usage du langage de la programmation orientée sur l'objet.
La liste @EXPORT
peut accepter des noms du module qui sont exportés de façon standard dans l'espace de nommage d'un script qui incorpore, lorsque pour l'incorporation, aucune liste d'importation n'est mentionnée. La liste @EXPORT_OK
accepte par contre les noms qu'un script qui incorpore peut intégrer au maximum dans son propre espace de nommage sans devoir les intégrer.
Dans l'exemple ci-dessus, dans le fichier module seul un nom est noté pour la liste @EXPORT
, à savoir un hash nommé %CHAMPS_FORMULAIRE
. Cette variable est exportée dans le script qui incorpore, quand, avec l'instruction use
, aucune liste d'importation n'est mentionnée. Pour la liste @EXPORT_OK
trois noms sont notés dans l'exemple: une scalaire nommée $pointeuse
, une liste nommée @donnees_log
et un sous-programme nommé recherche_client
.
Pour la notation des listes l'opérateur qw
est particulièrement le bienvenu, étant donné qu'il permet de noter les noms de variables sans devoir sans arrêt placer des guillemets. qw($pointeuse @donnees_log recherche_client)
correspond somme toute à la notation ('$pointeuse', '@donnees_log', 'recherche_client')
, mais est plus lisible.
Dans les parenthèses de qw
les noms souhaités sont notés séparés par des espaces. Les noms de variables reçoivent alors les signes distinctifs courants pour les scalaires, les listes et les hashes.
Le script qui incorpore dans l'exemple incorpore le module avec use moduletest
et doit mentionner dans la liste qui suit quels noms parmi ceux nommés dans @EXPORT
ou bien EXPORT_OK
il désire importer dans son propre espace de nommage. Dans l'exemple, seule la scalaire $pointeuse
est mentionnée et importée comme unique nom. Si vous omettez la mention de la liste (dans l'exemple donc que vous notiez seulement use moduletest;
), Les noms cités dans @EXPORT
seraient importés.
Vous devez suffisamment comprendre les modules que vous n'avez pas écrits vous même mais que vous désirez incorporer dans vos scripts, pour être en mesure d'en appeler les fonctions correctement, d'en connaître les variables qui a sont définies et de les utiliser etc... C'est pourquoi au moins tous les modules standard importants et les modules du répertoire CPAN sont documentés. Étant donné que des fichiers lisezmoi (readme) séparés se perdent facilement, Perl offre la possibilité, de noter la documentation dans le fichier avec le code source. Livré avec Perl, il y a le programme perldoc, avec lequel, vous pouvez sortir la partie documentation à l'écran.
L'exemple suivant montre le code complet d'un petit module standard de Perl. Le travail du module n'est pas intéressant à cet endroit. Il vise simplement à montrer comment la documentation est intégrée dans le code source.
package CPAN::Nox; BEGIN{$CPAN::Suppress_readline=1 unless defined $CPAN::term;} use CPAN; $VERSION = "1.00"; $CPAN::META->has_inst('MD5','no'); $CPAN::META->has_inst('LWP','no'); $CPAN::META->has_inst('Compress::Zlib','no'); @EXPORT = @CPAN::EXPORT; *AUTOLOAD = \&CPAN::AUTOLOAD; =head1 NAME CPAN::Nox - Wrapper around CPAN.pm without using any XS module =head1 SYNOPSIS Interactive mode: perl -MCPAN::Nox -e shell; =head1 DESCRIPTION This package has the same functionality as CPAN.pm, but tries to prevent the usage of compiled extensions during it's own execution. It's primary purpose is a rescue in case you upgraded perl and broke binary compatibility somehow. =head1 SEE ALSO CPAN(3) =cut |
L'exemple montre le code du module standard Nox.pm. La partie supérieure du fichier module contient le code exécutable proprement-dit du module et la partie inférieure du fichier module contient la documentation du module. La documentation commence avec des instructions qui débutent sur une nouvelle ligne et dont le premier caractère est un signe égal (=
). Avec =head1 NAME
par exemple un titre avec le texte NAME
est créé. Tout ce qui vient après est interprété comme documentation jusqu'à l'instruction de fin =cut
.
Pour pouvoir lire séparément la documentation, vous devez entrer sur la ligne d'invite de votre système d'exploitation:
perldoc [chemin]nom_module
Sous Windows vous pouvez utiliser la ligne d'invite de commandes DOS ou un programme qui est en mesure de capturer les résultats de la sortie standard d'un programme (certains des meilleurs éditeurs de texte le peuvent par exemple). Sur les systèmes Unix, utilisez simplement une console appropriée. Quand vous mentionnez le chemin d'un fichier module, vous pouvez séparer les répertoires par une barre oblique (/
). Ou bien vous passez dans le répertoire du fichier module, auquel cas vous pouvez omettre la mention de chemin.
Dans l'exemple ci-dessus du fichier module Nox.pm les appels suivants sont possibles:
perldoc CPAN::Nox
perldoc Nox.pm
perldoc Nox
perldoc -m Nox
(dresse la liste du code source aussi)
Modules standard de Perl | |
Fonctions pour les modules et progiciels (packages) | |
SELFHTML/Aides à la navigation CGI/Perl Modules Perl |
© 2001 Stefan Münz / © 2003 Traduction Serge François, 13405@free.fr
selfhtml@fr.selfhtml.org