web-dev-qa-db-fra.com

Comment "utiliser" un module Perl dans un répertoire qui n'est pas dans @INC?

J'ai un module dans le répertoire parent de mon script et je voudrais "l'utiliser".

Si je fais

use '../Foo.pm';

Je reçois des erreurs de syntaxe.

J'ai essayé de faire:

Push @INC, '..';
use EPMS;

et .. n'apparaît apparemment pas dans @INC

Je deviens fou! Qu'est-ce qui ne va pas ici?

51
Frew Schmidt

use a lieu au moment de la compilation, donc cela fonctionnerait:

BEGIN {Push @INC, '..'}
use EPMS;

Mais la meilleure solution est de use lib, ce qui est une meilleure façon d'écrire ce qui précède:

use lib '..';
use EPMS;

Dans le cas où vous exécutez à partir d'un répertoire différent, cependant, l'utilisation de FindBin est recommandée:

use FindBin;                     # locate this script
use lib "$FindBin::RealBin/..";  # use the parent directory
use EPMS;
93
ephemient

Il existe plusieurs façons de modifier @INC.

  • définissez Perl5LIB, comme indiqué dans perlrun

  • utilisez le commutateur -I sur la ligne de commande, également documenté dans perlrun . Vous pouvez également l'appliquer automatiquement avec Perl5OPT, mais utilisez simplement Perl5LIB si vous comptez le faire.

  • use lib à l'intérieur de votre programme, bien que cela soit fragile car une autre personne sur une autre machine peut l'avoir dans un répertoire différent.

  • Modifier manuellement @INC, en vous assurant de le faire au moment de la compilation si vous souhaitez insérer un module avec use. C'est trop de travail cependant.

20
brian d foy

Personnellement, je préfère garder mes modules (ceux que j'écris pour moi ou pour les systèmes que je peux contrôler) dans un certain répertoire, et aussi les placer dans un sous-répertoire. Un péché:

/www/modules/MyMods/Foo.pm
/www/modules/MyMods/Bar.pm

Et là où je les utilise:

use lib qw(/www/modules);
use MyMods::Foo;
use MyMods::Bar;

En aparté .. quand il s'agit de pousser, je préfère la virgule fléchée:

Push @array => $pushee;

Mais c'est juste une question de préférence.

12
Berserk

'use lib' est la réponse, comme @ephemient l'a mentionné plus tôt. Une autre option consiste à utiliser require/import au lieu d'utiliser. Cela signifie que le module ne serait pas chargé au moment de la compilation, mais plutôt lors de l'exécution.

Cela vous permettra de modifier @INC comme vous l'avez essayé là-bas, ou vous pourriez passer exiger un chemin d'accès au fichier au lieu du nom du module. Dans 'perldoc -f require':

Si EXPR est un mot simple, le require suppose une extension ".pm" et remplace "::" par "/" dans le nom de fichier, pour faciliter le chargement des modules standard. Cette forme de chargement des modules ne risque pas d'altérer votre espace de noms.

7
zigdon

Vous devez faire traiter Push avant que use soit - et use soit traité tôt. Vous aurez donc besoin d'un BEGIN { Push @INC, ".."; } pour avoir une chance, je crois.

2
Jonathan Leffler

Comme indiqué par "perldoc -f use":

C'est exactement équivalent à
BEGIN { require Module; import Module LIST; }
sauf que Module doit être un mot simple.

Autrement dit, "utiliser" équivaut à:

  • en cours d'exécution au moment de la compilation,
  • convertir le nom du package en nom de fichier,
  • require- ce nom de fichier, et
  • import- ce paquet.

Ainsi, au lieu d'appeler use, vous pouvez appeler require et importer dans un bloc BEGIN:

BEGIN {
  require '../EPMS.pm';
  EPMS->import();
}

Et bien sûr, si votre module ne fait aucune exportation de symboles ou autre initialisation lorsque vous appelez importation, vous pouvez laisser cette ligne:

BEGIN {
  require '../EPMS.pm';
}
1
Simon