web-dev-qa-db-fra.com

Comment utiliser un module Perl à partir d'un emplacement relatif?

J'ai un répertoire appelé foo, et en cela j'ai lib et bin. Les scripts dans bin ont besoin de choses dans lib. Je fais quelque chose comme ça:

#!Perl
use strict;
use warnings;
use lib '../lib';
use Foo; # <-- comes from lib

Mais cela signifie que je dois être dans le répertoire bin pour exécuter le script. Il y a sûrement un meilleur moyen. Quelle est la bonne façon de faire cela?

36
Frew Schmidt

Le module FindBin standard fait ce que vous voulez.

use FindBin;
use lib "$FindBin::Bin/../lib";

perldoc FindBin pour plus.

48
Michael Cramer

Analysez le chemin complet de votre .pl via __FILE__ et collez le ../lib à la fin ou affichez le dernier élément de split(/\//,__FILE__) et ajoutez /lib à celui-ci. 

5
Trey

J'utilise généralement cette technique. Il est malheureusement inspiré par mes PHP jours:

C'est pratique dans les situations où vous savez où un fichier donné sera sera relatif à celui en cours, et que vous n'êtes pas sûr des points d'entrée dans lesquels il peut être appelé ou de l'environnement environnant au moment de l'appel.

Cependant, j'utiliserais généralement cette technique seulement pour les scripts de test nécessitant des bibliothèques factices pour émuler des objets.

use File::Basename ();
use Cwd            ();
my $base_dir;
my $relative_path; 
BEGIN {
    $realitive_path = '../../' # Path to base of project relative to the current file
    $base_dir = Cwd::realpath( File::Basename::dirname(__FILE__) .'/' . $relative_path );
}


use lib "${base_dir}/lib";
use Foo;

Idéalement, il devrait y avoir un module quelque part qui le fasse, sinon, je suis à moitié tenté d’en écrire un:

use Some::Module ();
use lib Some::Module::relative_self('../../lib', __FILE__ ); 
3
Kent Fredric

Le module "FindBin" ne fonctionnera que si le répertoire dans lequel réside le script Perl se trouve dans votre système PATH, sinon il échouera. Pour surmonter cela vous pouvez manipuler la valeur $0 pour obtenir vos informations de chemin d'accès au module Perl et transmettre la valeur à use lib.

Quelque chose comme ça -

BEGIN {
    use File::Spec::Functions qw(rel2abs);
    use File::Basename qw(dirname);

    #Covert the script path to absolute and get its directory name
    our $path = dirname( rel2abs($0) );

    #Replace the bin tag with lib to get module directory
    $path =~ s{bin/?$}{lib};
}

use lib $path;

EDIT: Le module FindBin fonctionne parfaitement et peut être utilisé comme décrit dans Réponse de Michael . Ma compréhension de son fonctionnement était incomplète et m'a donc amené à faire le premier commentaire que je retire maintenant. Quoi qu'il en soit, je ne vois aucune raison pour que cette méthode ne fonctionne pas, mais avec quelques lignes de plus que ce qui pourrait être obtenu avec FindBin (TMTOWTDI).

3
aks

Juste pour ajouter mes propres deux cents à cette collection de réponses, je résous généralement ce problème en utilisant quelque chose dans ce sens:

use lib do {
    use Cwd 'realpath';
    my ($dir) = __FILE__ =~ m{^(.*)/};  # $dir = path of current file
    realpath("$dir/../lib");            # path of '../lib' relative to $dir
};

J'aime utiliser un bloc do car tout ce dont vous avez besoin y est contenu. Si vous avez besoin de copier/coller ou d'essayer de comprendre votre code ultérieurement, vous n'avez pas besoin de chercher un bloc BEGIN séparé ou quelque chose du genre.

Le code ci-dessus suppose naïvement que / est utilisé comme séparateur dir/nom de fichier.

0
zrajm

Ma solution:

use lib substr(__FILE__, 0, rindex (__FILE__, "/"));
0
Leo
use lib './';

travaille avec Perl v5.14.2 sur une machine Linux pour inclure des fichiers dans le même répertoire que mon script.

Peut-être que cela fonctionnerait pour vous de déplacer vos répertoires lib et bin sous le répertoire de travail de votre script et d'essayer de les référencer en utilisant 

use lib './bin/';
0
firetiger77