wake-up-neo.com

Wie ist Perls @INC aufgebaut? (aka Wie kann man beeinflussen, wo nach Perl-Modulen gesucht wird?)

Wie kann man beeinflussen, wo nach Perl-Modulen gesucht wird? oder, Wie ist Perls @INC aufgebaut ?

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

Da es auf StackOverflow anscheinend keinen umfassenden FAQ-Beitrag vom Typ "@INC" gibt, ist diese Frage als solche gedacht.

198
DVK

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

  1. Standard @INC

    Perl-Interpreter ist kompiliert mit einem bestimmten @INC - Standardwert . Um diesen Wert herauszufinden, führen Sie den Befehl env -i Perl -V Aus (env -i Ignoriert die Umgebungsvariable Perl5LIB - 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 -T (Verschmutzungsprüfungen aktiviert) ausgeführt wird.

Um den Standardpfad bei der Konfiguration der Perl-Binärkompilierung zu ändern, setzen Sie die Konfigurationsoption otherlibdirs :

Configure -Dotherlibdirs=/usr/lib/Perl5/site_Perl/5.16.3

  1. Umgebungsvariable Perl5LIB (Oder PERLLIB)

    Perl stellt @INC Mit einer Liste von Verzeichnissen (durch Doppelpunkte getrennt) voran, die in der Umgebungsvariablen Perl5LIB Ihrer Shell enthalten sind (falls diese nicht definiert ist, wird PERLLIB verwendet). Um den Inhalt von @INC Anzuzeigen, nachdem die Umgebungsvariablen Perl5LIB Und PERLLIB wirksam wurden, führen Sie Perl -V Aus.

    $ 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. Befehlszeilenoption -I

    Perl stellt @INC Mit einer Liste von Verzeichnissen (durch Doppelpunkte getrennt) voran, die als Wert der Befehlszeilenoption -I Übergeben wurden. Dies kann auf drei Arten erfolgen, wie bei Perl-Optionen üblich:

    • Übergeben Sie es in der 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 der Umgebungsvariablen Perl5OPT (Oder PERLOPT) (siehe Kapitel 19.02 in Programming Perl ).

  3. Übergeben Sie es über das lib Pragma

    Perl stellt @INC Mit einer Liste von Verzeichnissen voran, die ihm über use lib Übergeben wurden.

    In einem Programm:

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

    In der Befehlszeile:

    Perl -Mlib=/dir1,/dir2
    

    Sie können auch entfernen Sie die Verzeichnisse aus @INC Über no lib .

  4. Sie können @INC Direkt als reguläres Perl-Array bearbeiten.

    Hinweis: Da @INC Während der Kompilierungsphase verwendet wird, muss dies in einem Block BEGIN {} Erfolgen, der der Anweisung use MyModule Vorausgeht.

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

    • Fügen Sie am Ende Verzeichnisse mit Push @INC, $dir Hinzu.

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

Hinweis: Die Verzeichnisse sind nicht auf @INC In der in dieser Antwort angegebenen Reihenfolge verschoben , z. Standardmäßig steht @INC an letzter Stelle in der Liste, gefolgt von Perl5LIB, vorangestellt von -I, vorangestellt von use lib und direkter @INC Manipulation Die letzten beiden werden in der Reihenfolge gemischt, in der sie sich im Perl-Code befinden.

Verweise:

Es scheint keinen umfassenden Beitrag vom Typ @INC Zu Stack Overflow zu geben, daher ist diese Frage nur als solche gedacht.

Wann sollte jeder Ansatz angewendet 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 dem in der Perl-Binärdatei kompilierten Standardverzeichnis @INC Enthalten sein.

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

    Hinweis: Beachten Sie die üblichen Fallstricke bei Unix-Umgebungsvariablen - z. In bestimmten Fällen garantiert das Ausführen der Skripte als bestimmter Benutzer nicht, dass sie in der von diesem Benutzer eingerichteten Umgebung ausgeführt werden, z. über su.

  • Wenn die Module im Verzeichnis nur unter bestimmten Umständen verwendet werden müssen (z. B. wenn das Skript bzw. die Skripte im Entwicklungs-/Debug-Modus ausgeführt werden), können Sie entweder Perl5LIB Manuell festlegen oder -I Option zu Perl.

  • Wenn die Module nur für bestimmte Skripte verwendet werden müssen, verwenden Sie use lib/no lib, Wenn alle Benutzer sie verwenden. Pragmas im Programm selbst. Sie sollte auch verwendet werden, wenn das zu durchsuchende Verzeichnis zur Laufzeit dynamisch bestimmt werden muss - z. aus den Befehlszeilenparametern des Skripts oder dem Pfad des Skripts (siehe FindBin für einen sehr nützlichen Anwendungsfall).

  • Wenn die Verzeichnisse in @INC Nach einer komplizierten Logik manipuliert werden müssen, die entweder durch die Kombination von use lib/no lib - Pragmas unmöglich oder zu unhandlich zu implementieren ist, verwenden Sie direkt @INC Manipulation innerhalb des Blocks BEGIN {} Oder innerhalb einer Spezialbibliothek, die für die Manipulation von @INC Vorgesehen ist und von Ihren Skripten verwendet werden muss, bevor andere Module verwendet werden.

    Ein Beispiel hierfür ist das automatische Wechseln zwischen Bibliotheken in den Verzeichnissen prod/uat/dev und das Abholen von Wasserfallbibliotheken in prod, wenn diese in dev und/oder UAT fehlen (die letzte Bedingung macht die Standardlösung "use lib + FindBin" ziemlich kompliziert. A Eine detaillierte Darstellung dieses Szenarios finden Sie in Wie verwende ich Beta-Perl-Module aus Beta-Perl-Skripten? .

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

252
DVK

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. Die in dieser Datei aufgelisteten Pfade werden zur Laufzeit an @INC angehängt.

  2. Die Datei /Library/Perl/x.xx/PrependToPath. In dieser Datei aufgeführte Pfade werden zur Laufzeit vor @INC gestellt.

17
dgatwood

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

Mein CGI REST Skript sieht so 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.

6
Kacper Perschke