Comment mon script Perl peut-il trouver son module dans le même répertoire?

J’ai récemment écrit un nouveau script Perl pour tuer les processus basés sur le nom du processus / nom d’utilisateur et les étendre à l’aide de classes afin de pouvoir réutiliser le code de processus dans d’autres programmes. Ma disposition actuelle est –

/home/mutew/src/prod/pskill <-- Perl script /home/mutew/src/prod/Process.pm <-- Package to handle process descriptions 

J’ai ajouté ~ / src / prod dans ma variable $ PATH pour accéder au script depuis n’importe où. En exécutant le script depuis un répertoire autre que son répertoire résident, on obtient un “Impossible de localiser Process.pm dans @INC” (ce qui est compréhensible vu que, hormis les répertoires partagés dans / usr, @INC n’inclut que le répertoire actuel – ‘.’). Une solution de contournement que j’ai utilisé est la directive d’utilisation lib comme tel –

 use lib '/home/mutew/src/prod'; 

mais c’est un problème majeur de portabilité. Des solutions qui me permettront également d’exporter le script vers d’autres systèmes sans modification?


MODIFIER

  1. J’ai choisi la réponse ‘depesz’ comme étant correcte en raison de sa simplicité et de son utilisation de base du module.
  2. La réponse de Brian Foy suggère toutefois d’autres méthodes pour accomplir la même chose (TMTOWTDI), sa consortingbution dans perlfaq8 rend cette question absolument superflue.

L’approche la plus simple m’a semblé utiliser le module FindBin. Comme ça:

 use FindBin; use lib $FindBin::Bin; 

En général, je préfère que mes scripts soient fournis de telle manière que les programmes soient dans n’importe quel / bin et que les bibliothèques soient dans quelque / lib

Dans ces situations, j’utilise une approche légèrement plus compliquée:

 use Cwd qw(abs_path); use FindBin; use lib abs_path("$FindBin::Bin/../lib"); 

L’appel abs_path est de faire en sorte que @INC contienne quelque chose / lib, et pas n’importe quel / bin /../ lib – c’est juste un léger changement, mais cela facilite la lecture des messages d’erreur.

Je suis curieux de savoir pourquoi la solution simpliste

 use File::Basename; use lib dirname (__FILE__); use SomeModuleLocatedInTheSameDirectoryAsThisPerlScriptOrModule; 

ne s’est pas levé. Le module FindBin semble avoir quelques problèmes si le fichier n’est pas le script Perl exécutable principal, mais simplement un module Perl non exécutable. C’est du moins comme ça que j’interprète le commentaire dans la documentation . Je n’ai pas vraiment testé.

Pour avoir un autre chemin par rapport à l’emplacement de ce fichier Perl, faites comme:

 use File::Basename; use lib dirname (__FILE__) . "/MyModules"; 

De perlfaq8 , qui répond “Comment append un répertoire à mon chemin d’inclusion (@INC) lors de l’exécution?” . Il existe également plusieurs autres réponses aux questions concernant ce problème.


Comment append un répertoire à mon chemin d’inclusion (@INC) lors de l’exécution?

Voici les moyens suggérés de modifier votre chemin d’inclusion, y compris les variables d’environnement, les commutateurs d’exécution et les instructions dans le code:

la variable d’environnement PERLLIB

 $ export PERLLIB=/path/to/my/dir $ perl program.pl 

la variable d’environnement PERL5LIB

 $ export PERL5LIB=/path/to/my/dir $ perl program.pl 

l’indicateur de ligne de commande perl -Idir

 $ perl -I/path/to/my/dir program.pl 

l’utilisation lib pragma:

 use lib "$ENV{HOME}/myown_perllib"; 

Le dernier est particulièrement utile car il connaît les architectures dépendantes de la machine. Le module pragmatique lib.pm a été inclus pour la première fois dans la version 5.002 de Perl.

Jetez un oeil à Par :: Packer . Il crée un exécutable avec toutes les dépendances du script. Cela facilite la dissortingbution. Vous pouvez également fournir à vos utilisateurs une version de votre module pouvant être installée sur leurs systèmes. Voir Module :: Starter pour un moyen simple de générer tous les fichiers requirejs pour effectuer une dissortingbution de style CPAN standard.

Vous pouvez effectuer une recherche perl dans n’importe quel répertoire en utilisant l’ -I . Ici, -I signifie @INC qui est le tableau de chemins dans lequel perl recherche les modules. Utiliser -I ajoute le chemin donné au tableau @INC pour cette exécution.

par exemple:

 perl -I lib bin/script.pl 

où lib contient les modules que je veux utiliser.

Je sais que cela fonctionne pour Perl 5 . Je ne suis pas sûr des autres versions.

Pour convertir des liens relatifs en absolu et append à @INC, j’utilise normalement ex :: lib. Bien entendu, cela n’est utile que si vous prévoyez de conserver les emplacements relatifs du script et du module identiques sur toutes les machines sur lesquelles vous prévoyez d’exécuter votre script.

FindBin :: libs trouvera toutes vos bibliothèques placées à des endroits raisonnables par rapport au chemin à partir duquel votre script est exécuté.

Restez simple Il n’est pas nécessaire d’importer des bibliothèques; il suffit de trouver votre répertoire de travail actuel:

 use lib "$ENV{PWD}/relativ_path_own_perllib"; 

Pour des problèmes similaires, vous pouvez lire la variable d’environnement qui vous donne des informations sur votre emplacement, votre répertoire personnel, les éléments du système d’exploitation, etc., avec une seule ligne de code de programmation dans le terminal, comme:

 perl -e 'map { print; print " : ". $ENV{$_}." \n\r"; } sort keys %ENV ' 

Il n’y a pas besoin de lier certaines bibliothèques; utilisez simplement le %ENV-Hash .