Wie ist Perls @INC aufgebaut? (aka Wie können Sie beeinflussen, wo nach Perl-Modulen gesucht wird?)

199

Welche Auswirkungen haben die Auswirkungen darauf, wo nach Perl-Modulen gesucht wird? oder Wie ist Perls @INC aufgebaut ?

Wie wir wissen, verwendet Perl ein @INCArray mit Verzeichnisnamen, um zu bestimmen, wo nach Perl-Moduldateien gesucht werden soll .

Es scheint keinen umfassenden FAQ-Beitrag vom Typ "@INC" auf StackOverflow zu geben, daher ist diese Frage als eine Frage gedacht.

DVK
quelle
7
Ja, aber es gibt eine sehr gute unter search.cpan.org/perldoc/… ?
Mob
3
@mobrule: Ich denke, das ist bei weitem nicht so umfassend - es sagt nur, wie man zur @INCLaufzeit etwas hinzufügt , nicht die vollständige Konstruktion.
Cascabel
2
@mobrule - @Jefromi richtig geraten - das Hauptproblem mit ANY und alle Referenzen , die ich bisher gefunden ein Mangel an umfassenden Informationen war auf perl binär den einkompilierte in Standard @INC
DVK
3
Einige können diese Antwort so umfassend machen, indem sie mir einen Patch senden. Es ist einfach, weil Perlfaq in Github ist. :)
Brian D Foy
1
Nun, die "umfassende Information über die kompilierte Standardeinstellung @INC der Perl-Binärdatei" ist, dass es die Person ist, die sie eingerichtet hat. Wenn Sie nach den verschiedenen Wegen fragen, die dort hineinkommen, dann haben Sie meiner Meinung nach eine andere Frage als die, die Sie beantwortet haben.
Brian D Foy

Antworten:

254

Wir werden uns ansehen, wie der Inhalt dieses Arrays aufgebaut ist und manipuliert werden kann, um zu beeinflussen, wo der Perl-Interpreter die Moduldateien findet.

  1. Standard @INC

    Perl-Interpreter wird mit einem bestimmten @INCStandardwert kompiliert . Um diesen Wert herauszufinden, führen Sie den env -i perl -VBefehl aus ( env -iignoriert die PERL5LIBUmgebungsvariable - siehe # 2) und in der Ausgabe sehen Sie ungefähr Folgendes:

    $ env -i perl -V
    ...
    @INC:
     /usr/lib/perl5/site_perl/5.18.0/x86_64-linux-thread-multi-ld
     /usr/lib/perl5/site_perl/5.18.0
     /usr/lib/perl5/5.18.0/x86_64-linux-thread-multi-ld
     /usr/lib/perl5/5.18.0
     .

Beachten Sie .am Ende; Dies ist das aktuelle Verzeichnis (das nicht unbedingt mit dem Verzeichnis des Skripts identisch ist). Es fehlt in Perl 5.26+ und wenn Perl mit ausgeführt wird -T(Taint Checks aktiviert) .

Legen Sie die Konfigurationsoption fest, um den Standardpfad beim Konfigurieren der Perl-Binärkompilierung zu ändern otherlibdirs:

Configure -Dotherlibdirs=/usr/lib/perl5/site_perl/5.16.3

  1. Umgebungsvariable PERL5LIB(oder PERLLIB)

    Perl wird @INCmit einer Liste von Verzeichnissen (durch Doppelpunkte getrennt) versehen, die in der Umgebungsvariablen Ihrer Shell enthalten sind PERL5LIB(sofern diese nicht definiert ist, PERLLIBwird sie verwendet). Führen Sie Folgendes aus, um anzuzeigen, dass der Inhalt von @INCAfter- PERL5LIBund PERLLIBUmgebungsvariablen wirksam geworden ist perl -V.

    $ perl -V
    ...
    %ENV:
      PERL5LIB="/home/myuser/test"
    @INC:
     /home/myuser/test
     /usr/lib/perl5/site_perl/5.18.0/x86_64-linux-thread-multi-ld
     /usr/lib/perl5/site_perl/5.18.0
     /usr/lib/perl5/5.18.0/x86_64-linux-thread-multi-ld
     /usr/lib/perl5/5.18.0
     .
  2. -I Befehlszeilenoption

    Perl wird @INCmit einer Liste von Verzeichnissen (durch Doppelpunkte getrennt) versehen, die als Wert der -IBefehlszeilenoption übergeben werden. Dies kann wie bei Perl-Optionen üblich auf drei Arten erfolgen:

    • Übergeben Sie es über die Befehlszeile:

      perl -I /my/moduledir your_script.pl
    • Übergeben Sie es über die erste Zeile (shebang) Ihres Perl-Skripts:

      #!/usr/local/bin/perl -w -I /my/moduledir
    • Übergeben Sie es als Teil einer PERL5OPT(oder PERLOPT) Umgebungsvariablen (siehe Kapitel 19.02 in Programming Perl ).

  3. Übergeben Sie es über das libPragma

    Perl stellt @INCeine Liste der Verzeichnisse voraus, die über perl übergeben wurden use lib.

    In einem Programm:

    use lib ("/dir1", "/dir2");

    In der Befehlszeile:

    perl -Mlib=/dir1,/dir2

    Sie können die Verzeichnisse auch aus @INCvia entfernenno lib .

  4. Sie können direkt @INCals reguläres Perl-Array bearbeiten.

    Hinweis: Da dies @INCwährend der Kompilierungsphase verwendet wird, muss dies innerhalb eines BEGIN {}Blocks erfolgen, der der use MyModuleAnweisung vorausgeht .

    • Fügen Sie am Anfang Verzeichnisse über hinzu unshift @INC, $dir.

    • Fügen Sie am Ende Verzeichnisse über hinzu push @INC, $dir.

    • Machen Sie alles andere, was Sie mit einem Perl-Array tun können.

Hinweis: Die Verzeichnisse werden unverschoben auf @INCin der Reihenfolge , in dieser Antwort enthalten ist, zB Standard @INCist zuletzt in der Liste vorangestellt ist PERL5LIB, vorangestellt -I, mit vorangestellter use libund direkter @INCManipulation, wobei die beiden letzteren gemischt in beliebiger Reihenfolge sie sind in Perl - Code.

Verweise:

Es scheint keinen umfassenden @INCFAQ-Beitrag zum Stapelüberlauf zu geben, daher ist diese Frage als eine Frage gedacht.

Wann sollte jeder Ansatz verwendet werden?

  • Wenn die Module in einem Verzeichnis von vielen / allen Skripten auf Ihrer Site verwendet werden müssen, insbesondere von mehreren Benutzern, sollte dieses Verzeichnis in der Standardeinstellung enthalten sein, @INCdie in die Perl-Binärdatei kompiliert wurde.

  • Wenn die Module im Verzeichnis ausschließlich von einem bestimmten Benutzer für alle vom Benutzer ausgeführten Skripts verwendet werden (oder wenn das Neukompilieren von Perl keine Option ist, um die Standardeinstellung @INCim vorherigen Anwendungsfall zu ändern ), legen Sie die Module PERL5LIBnormalerweise während der Benutzeranmeldung fest.

    Hinweis: Bitte beachten Sie die üblichen Fallstricke bei Unix-Umgebungsvariablen. In bestimmten Fällen garantiert das Ausführen der Skripte als bestimmter Benutzer nicht, dass sie mit der eingerichteten Umgebung dieses Benutzers ausgeführt werden, z su. B. über .

  • Wenn die Module im Verzeichnis nur unter bestimmten Umständen verwendet werden müssen (z. B. wenn die Skripte im Entwicklungs- / Debug-Modus ausgeführt werden), können Sie sie entweder PERL5LIBmanuell festlegen oder die -IOption an Perl übergeben.

  • Wenn die Module nur für bestimmte Skripte von allen Benutzern verwendet werden müssen, verwenden Sie use lib/ no libpragmas im Programm selbst. Es sollte auch verwendet werden, wenn das zu durchsuchende Verzeichnis zur Laufzeit dynamisch bestimmt werden muss - z. B. anhand der Befehlszeilenparameter oder des Skriptpfads des Skripts (ein sehr nützlicher Anwendungsfall finden Sie im FindBin- Modul).

  • Wenn die Verzeichnisse @INCnach einer komplizierten Logik manipuliert werden müssen, die entweder nicht zu unhandlich ist, um durch Kombination von use lib/ no libpragmas implementiert zu werden , verwenden Sie die direkte @INCManipulation innerhalb des BEGIN {}Blocks oder innerhalb einer für die @INCManipulation vorgesehenen Spezialbibliothek , die von Ihrem Skript verwendet werden muss (s) bevor andere Module verwendet werden.

    Ein Beispiel hierfür ist das automatische Wechseln zwischen Bibliotheken in den Verzeichnissen prod / uat / dev, wobei die Wasserfallbibliothek in prod aufgenommen wird, wenn sie in dev und / oder UAT fehlt (die letzte Bedingung macht die Standardlösung "use lib + FindBin" ziemlich kompliziert. A. detaillierte Darstellung dieses Szenarios ist in Wie verwende ich beta - Perl - Module von beta Perl - Skripte? .

  • Ein zusätzlicher Anwendungsfall für die direkte Bearbeitung @INCbesteht darin, Unterprogrammreferenzen oder Objektreferenzen hinzufügen zu können (ja, Virginia @INCkann benutzerdefinierten Perl-Code und nicht nur Verzeichnisnamen enthalten, wie unter Wann wird eine Unterprogrammreferenz in @INC aufgerufen? ) Erläutert .

DVK
quelle
1
Vergessen Sie nicht PERLOPT, wo Sie -I einstellen können. Außerdem verwenden Dinge wie base.pm und local :: lib die Dinge, die Sie implizit aufgelistet haben.
Brian D Foy
1
@brian - use :: base verwendet es aufgrund von "require" darunter, IIRC. Ich bin nicht mit local :: lib vertraut, muss mehr lesen, um zu verstehen, worum es geht
DVK
3
Um dies zu einer wirklich guten Antwort zu machen, müssen Sie den Leuten auch sagen, wann sie jede verwenden sollen. Nur 10 Optionen zu geben, wie sie könnten, ist nicht sehr hilfreich. :)
Brian D Foy
PS: Jeder kann die Antwort so bearbeiten, dass sie über -I / use lib ein zweites architekturspezifisches Verzeichnis enthält. Ich hatte vor, dies zu einem späteren Zeitpunkt selbst zu tun, muss aber erst einmal offline gehen.
DVK
@brian - PERLOPT hinzugefügt. Ich möchte base.pm und andere "Wann wird @INC verwendet" -Elemente erwähnen, die besser für die @ INC / Finding-Moduldateien geeignet sind.
DVK
18

Zusätzlich zu den oben aufgeführten Speicherorten bietet die OS X-Version von Perl zwei weitere Möglichkeiten:

  1. Die Datei /Library/Perl/x.xx/AppendToPath. In dieser Datei aufgeführte Pfade werden zur Laufzeit an @INC angehängt.

  2. Die Datei /Library/Perl/x.xx/PrependToPath. Die in dieser Datei aufgeführten Pfade werden zur Laufzeit an @INC vorangestellt.

dgatwood
quelle
6

Wie bereits gesagt, ist @INC ein Array und Sie können alles hinzufügen, was Sie wollen.

Mein CGI REST-Skript sieht folgendermaßen aus:

#!/usr/bin/perl
use strict;
use warnings;
BEGIN {
    push @INC, 'fully_qualified_path_to_module_wiht_our_REST.pm';
}
use Modules::Rest;
gone(@_);

Unterprogramm weg wird von Rest.pm exportiert.

Kacper Perschke
quelle