wake-up-neo.com

Wie verwende ich ein Perl-Modul von einem relativen Standort aus?

Ich habe ein Verzeichnis namens foo und darin lib und bin. Die Skripte in bin brauchen Sachen in lib. Ich mache so etwas:

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

Das bedeutet aber, dass ich mich im Verzeichnis bin befinden muss, um das Skript auszuführen. Sicher gibt es einen besseren Weg. Was ist der richtige Weg, um dies zu tun?

36
Frew Schmidt

Das Standardmodul FindBin macht, was Sie möchten.

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

perldoc FindBin für mehr.

48
Michael Cramer

Durchsuchen Sie den vollständigen Pfad zu Ihrem .pl über __FILE__ und markieren Sie den ../lib am Ende, oder entfernen Sie das letzte Element von split(/\//,__FILE__) und fügen Sie /lib hinzu. 

5
Trey

Ich verwende diese Technik im Allgemeinen. Es ist leider aus meinen PHP Tagen inspiriert:

Dies ist in Situationen nützlich, in denen Sie wissen, wo eine bestimmte Datei ist relativ zur aktuellen Datei ist, und sich nicht sicher sind, welche Einstiegspunkte in der Umgebung oder während der Aufrufzeit aufgerufen werden.

Normalerweise würde ich diese Technik only jedoch für Testskripte verwenden, die Dummy-Bibliotheken zum Emulieren von Dingen benötigen.

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;

Im Idealfall sollte es irgendwo ein Modul geben, das dies tut. Wenn nicht, bin ich halb versucht, eines zu schreiben:

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

Das "FindBin" -Modul funktioniert nur, wenn sich das Verzeichnis, in dem sich das Perl-Skript befindet, in Ihrem Systempfad befindet, andernfalls schlägt es fehl. Um das zu überwinden Sie können den $0-Wert bearbeiten, um die Informationen zum Pfad zum Perl-Modul abzurufen und den Wert an use lib zu übergeben.

Etwas wie das -

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: Das FindBin-Modul funktioniert einwandfrei und kann wie in Michaels Antwort beschrieben verwendet werden. Mein Verständnis für seine Arbeitsweise war unvollständig und führte mich dazu, den ersten Kommentar abzugeben, den ich jetzt zurücknehme. Ich sehe jedenfalls keinen Grund, warum diese Methode nicht funktionieren sollte, allerdings mit ein paar Zeilen mehr, als mit FindBin (TMTOWTDI) möglich wäre.

3
aks

Um meiner Antwortsammlung zwei eigene Cents hinzuzufügen, löse ich dieses Problem in der Regel mit folgenden Begriffen:

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

Ich mag es, einen do-Block zu verwenden, weil alles Notwendige so sauber darin enthalten ist. Wenn Sie jemals kopieren/einfügen oder versuchen müssen, Ihren Code zu einem späteren Zeitpunkt zu verstehen, müssen Sie nicht nach einem separaten BEGIN-Block oder ähnlichem suchen.

Der obige Code geht naiv davon aus, dass / als Trennzeichen für Verzeichnisse/Dateinamen verwendet wird.

0
zrajm

Meine Lösung:

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

hat für mich mit Perl v5.14.2 an einer Linux-Box gearbeitet, um Dateien in das gleiche Verzeichnis wie mein Skript aufzunehmen.

Vielleicht würde es für Sie funktionieren, Ihre lib- und bin-Verzeichnisse unter das Arbeitsverzeichnis Ihres Skripts zu verschieben und sie mithilfe von zu referenzieren 

use lib './bin/';
0
firetiger77