web-dev-qa-db-fra.com

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 je l'ai étendu à 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 de n'importe où. L'exécution du script à partir de tout répertoire autre que son répertoire résident entraîne un "Impossible de localiser Process.pm dans @INC" (ce qui est compréhensible étant donné que, à part les répertoires partagés dans/usr, @INC inclut uniquement le répertoire actuel - '.'). Une solution de contournement que j'utilise est la directive use lib comme telle -

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 et changements?


MODIFIER

  1. J'ai choisi la réponse "depesz" comme étant la bonne en raison de sa simplicité et de l'utilisation du module principal.
  2. la réponse de brian d foy suggère cependant d'autres méthodes pour y parvenir (TMTOWTDI), sa contribution dans perlfaq8 rend cette question absolument redondante.
49
aks

L'approche la plus simple que j'ai trouvée consiste à 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 manière à ce que les programmes se trouvent dans le répertoire/bin et les bibliothèques dans le répertoire/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 consiste à faire en sorte que @INC contienne tout/lib, et non pas/bin /../ lib - c'est juste un léger changement, mais cela facilite la lecture des messages d'erreur.

51
user80168

Je suis curieux de savoir pourquoi la solution simpliste

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

n'est pas venu. 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 ainsi que j'interprète le commentaire dans la documentation . Je ne l'ai pas vraiment testé.

Pour avoir un autre chemin d'accès par rapport à l'emplacement de ce fichier Perl, faites quelque chose comme

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

De perlfaq8 , qui répond "Comment ajouter 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 ajouter un répertoire à mon chemin d'inclusion (@INC) lors de l'exécution?

Voici les façons suggérées 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";

Ce 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 avec la version 5.002 de Perl.

13
brian d foy

Jetez un oeil à Par :: Packer . Il crée un exécutable avec toutes les dépendances du script incluses. Cela facilite la distribution. Vous pouvez également fournir à vos utilisateurs une version de votre module qui peut être installée sur leurs systèmes. Voir Module :: Starter pour un moyen facile de construire tous les fichiers requis pour faire une distribution standard de style CPAN.

3
Chas. Owens

Vous pouvez faire apparaître Perl dans n'importe quel répertoire en utilisant le -I drapeau. Ici, -I signifie @INC qui est le tableau des chemins dans lesquels Perl recherche les modules. En utilisant -I ajoute le chemin donné au @INC tableau 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.

2
Vikas

Outre les solutions déjà énoncées:

  1. utiliser FindBin/lib
  2. Perl Faq 8 Comment ajouter un répertoire à mon chemin d'inclusion (@INC) lors de l'exécution?

"L'approche la plus simple" (™) que j'utilise lors du développement/test d'un module avant de le déployer (dans/usr/local/lib/site_Perl/ou ailleurs dans @INC) consiste à modifier @INC avant de charger le module comme suit:

#!/usr/bin/Perl
use strict;
use warnings;
# Modify @INC prior to module loading.
BEGIN { unshift @INC, '.'; }
use YourModuleInCWD;

( Ajouter le répertoire de travail actuel à @INC? - PerlMonks )

1
Robert

Pour convertir des liens relatifs en absolus et les ajouter à @INC, j'utilise normalement ex :: lib. Bien sûr, 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.

0
Ya. Perelman