2009-04-08 5 views
40

Ich schrieb vor kurzem ein neues Perl-Skript, um Prozesse basierend auf entweder Prozessname/Benutzernamen zu beenden und es mit Klassen zu erweitern, so dass ich den Prozesscode in anderen Programmen wiederverwenden konnte. Mein derzeitiges Layout ist -Wie kann mein Perl-Skript sein Modul im selben Verzeichnis finden?

Ich habe ~/src/prod in meine Variable $ PATH hinzugefügt, um von überall auf das Skript zuzugreifen. Wenn das Skript von einem anderen Verzeichnis als seinem residenten Verzeichnis ausgeführt wird, führt dies zu einem "Prozess.pm in @INC kann nicht gefunden werden" (was verständlich ist, da andere als die freigegebenen Verzeichnisse in/usr nur das aktuelle Verzeichnis enthalten.) "."). Eine Problemumgehung, die ich verwendet habe, ist die Verwendung der lib-Direktive, so ist dies ein großes Portabilitätsproblem. Irgendwelche Lösungen, die es mir erlauben, das Skript auch ohne Änderungen auf andere Systeme zu exportieren?


EDIT

  1. ich wegen seiner Einfachheit und Kernmodul Nutzung 'depesz' Antwort als richtig gewählt haben.
  2. brian d foys Antwort schlägt zwar andere Methoden vor, um dasselbe zu erreichen (TMTOWTDI), aber sein Beitrag in Perlfaq8 macht diese Frage absolut überflüssig.
+0

vielleicht ist es nur meine Installation, aber wenn beide Dateien im selben Verzeichnis sind, verwende ich einfach "FILENAME.pm". Dann "mein $ newVar = PACKAGENAME-> new();" für jede Objektprogrammierung. –

+0

Wow, das sollte in Perl viel einfacher sein! Machen Sie die einfachen Dinge einfach usw. –

Antwort

42

Der einfachste Ansatz fand ich es FindBin-Modul zu verwenden. Wie folgt aus:

use FindBin; 
use lib $FindBin::Bin; 

Im Allgemeinen ziehe ich meine Skripte haben, in der Weise vorgesehen, die Programme sind in jedem/sind, und Bibliotheken sind in was auch immer/lib

In diesen Situationen verwende ich ein etwas komplizierteren Ansatz:

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

der abs_path Aufruf ist die @INC enthalten unabhängig von/lib zu machen, und nicht, was/bin /../ lib - es ist nur eine leichte Veränderung, macht aber das Lesen Fehlermeldungen einfacher.

+3

Vergessen Sie nicht, dass abs_path im Taint-Modus verschmutztes Ergebnis zurückgibt. Sie müssen 'usage lib (abs_path (" $ FindBin :: Bin /../ lib ") = ~ m {^ (/.*)}) [0] verwenden;' oder benutzen Sie einfach 'usage lib" $ FindBin :: Bin /../ lib "; weil es keinen Grund gibt, den Pfad zu kanonisieren. –

3

Werfen Sie einen Blick auf Par::Packer. Es erstellt eine ausführbare Datei mit allen Abhängigkeiten des Skripts. Es erleichtert die Verteilung. Sie können Ihren Benutzern auch eine Version Ihres Moduls bereitstellen, die auf ihren Systemen installiert werden kann. Unter Module::Starter finden Sie eine einfache Möglichkeit zum Erstellen aller Dateien, die für die Erstellung einer standardmäßigen CPAN-Verteilung erforderlich sind.

9

Von perlfaq8, die Antworten "How do I add a directory to my include path (@INC) at runtime?". Für Fragen zu diesem Thema gibt es mehrere Antworten.


Wie füge ich zur Laufzeit ein Verzeichnis zu meinem Include-Pfad (@INC) hinzu?

Hier sind die vorgeschlagenen Möglichkeiten der Modifizierung Ihren Weg umfassen, einschließlich Umgebungsvariablen, Laufzeitschalter, und in-Code-Anweisungen:

die PERLLIB Umgebungsvariable

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

die PERL5LIB Umgebungsvariable

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

die perl -Idir Befehlszeilenparametern

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

die Verwendung lib-Pragma:

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

Die letzte ist besonders nützlich, da es sich um maschinenabhängige Architekturen kennt. Das pragmatische Modul lib.pm wurde erstmals in Perl 5.002 integriert.

+0

Ich las später noch am selben Tag perlfaq8 und fand die Antwort, die ich in Ihrem Beitrag brauchte. Ich frage mich, warum du die zweite Methode benutzt hast (benutze Cwd), da @INC bereits einen Eintrag für das aktuelle Verzeichnis hat - '.' – aks

0

Um relative Links in absolute zu konvertieren und @INC hinzuzufügen, verwende ich normalerweise ex :: lib. Dies ist natürlich nur dann nützlich, wenn Sie beabsichtigen, die relativen Speicherorte des Skripts und des Moduls auf allen Computern identisch zu halten, auf denen Sie das Skript ausführen möchten.

38

Ich bin neugierig, warum die vereinfachende Lösung

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

nicht kommen. Das FindBin-Modul scheint einige Probleme zu haben, wenn es sich bei der Datei nicht um das Hauptprogramm für ausführbare Perl handelt, sondern einfach um ein nicht ausführbares Perl-Modul. Zumindest interpretiere ich den Kommentar in der documentation. Habe es nicht wirklich getestet.

Um andere Pfad relativ zur Position dieser Datei Perl haben, tun so etwas wie

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

Ich mag diesen Ansatz sehr - ich musste nur 'cwd verwenden qw (abs_path); benutze lib dirname (abs_path (__ FILE __)); 'um das Skript über einen Symlink aufrufbar zu machen. Prost! – sdaau

+0

Dies ist die einzige Antwort hier, die funktioniert –

+0

genial! Das funktioniert! –

-1

FindBin::libs auf den Weg zu angemessenen Orten relativ platziert alle Libs finden, von wo aus das Skript ausgeführt wird.

-1

Halten Sie es einfach. Sie müssen keine Bibliotheken importieren. können Sie die aktuelle Arbeitsverzeichnis herausfinden:

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

Für ähnliche Probleme haben, können Sie die Umgebungsvariable ausgelesen werden, die über Ihre Informationen gibt, wo Sie sind, Ihr Home-Verzeichnis, das Betriebssystem Sachen, und so weiter, mit nur einem Reihe von Programmcode in dem Shell-Terminal, wie:

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

Es gibt keine Notwendigkeit, einige Bibliotheken zu binden; Verwenden Sie einfach die %ENV-Hash.

+0

'$ ENV {PWD}' löst das Problem nicht - im Gegenteil. Es gibt das Arbeitsverzeichnis des Benutzers zurück, nicht den Speicherort des Skripts. – pipe

0

Mit dem Flag -I können Sie perl in jedes Verzeichnis suchen. Hier steht -I für @INC, das ist das Array von Pfaden, in denen Perl nach Modulen sucht. Die Verwendung von -I fügt den angegebenen Pfad für diese Ausführung zum Array @INC hinzu.

zB:

perl -I lib bin/script.pl 

wo lib die Module enthält das ich verwenden möchte.

Ich weiß, dass dies für perl 5 funktioniert. Ich bin mir nicht sicher über andere Versionen.

Verwandte Themen