Jak zbudowana jest @INC Perla? (aka Jakie są wszystkie sposoby wpływania na to, gdzie moduły Perla są wyszukiwane?)

199

Jakie są wszystkie sposoby wpływania na to, gdzie moduły Perla są wyszukiwane? lub, jak zbudowana jest @INC Perla ?

Jak wiemy, Perl używa @INCtablicy zawierającej nazwy katalogów, aby określić, gdzie szukać plików modułu Perla .

Wydaje się, że nie ma obszernego postu typu „@INC” FAQ na StackOverflow, więc to pytanie jest zamierzone jako jedno.

DVK
źródło
7
Tak, ale jest całkiem dobry na search.cpan.org/perldoc/… ?
tłum
3
@mobrule: Nie wydaje mi się, żeby było to tak kompleksowe - po prostu mówi, jak dodać @INCw czasie wykonywania, a nie pełną konstrukcję.
Cascabel
2
@mobrule - @Jefromi zgadł dobrze - głównym problemem z DOWOLNYMI i wszystkimi referencjami, które do tej pory znalazłem, był brak wyczerpujących informacji na temat domyślnie skompilowanych plików binarnych perla @INC
DVK
3
Niektórzy mogą uczynić tę odpowiedź tak wyczerpującą, wysyłając mi łatkę. To proste, ponieważ perlfaq jest w Github. :)
brian d foy
1
Cóż, „wyczerpująca informacja o domyślnym @INC wkompilowanym pliku binarnym perla” jest taka, że ​​skonfigurowała go osoba, która go skompilowała. Jeśli pytasz o różne ścieżki, które tam prowadzą, myślę, że masz inne pytanie niż to, na które odpowiedziałeś.
brian d foy

Odpowiedzi:

254

Przyjrzymy się, jak konstruowana jest zawartość tej tablicy i można nią manipulować, aby wpłynąć na to, gdzie interpreter Perla znajdzie pliki modułów.

  1. Domyślna @INC

    Interpreter języka Perl jest kompilowany z określoną @INCwartością domyślną . Aby znaleźć tę wartość, uruchom env -i perl -Vpolecenie ( env -iignoruje PERL5LIBzmienną środowiskową - patrz # 2), a na wyjściu zobaczysz coś takiego:

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

Uwaga .na końcu; jest to katalog bieżący (niekoniecznie taki sam jak katalog skryptu). Brakuje go w Perlu 5.26+, a gdy Perl działa z -T(włączone testy skażenia) .

Aby zmienić domyślną ścieżkę podczas konfigurowania kompilacji binarnej Perla, ustaw opcję konfiguracji otherlibdirs:

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

  1. Zmienna środowiskowa PERL5LIB(lub PERLLIB)

    Perl uprzednio oczekuje @INCna listę katalogów (oddzielonych dwukropkami) zawartych w PERL5LIB(jeśli nie jest zdefiniowana, PERLLIBużywana) zmiennej środowiskowej powłoki. Aby zobaczyć zawartość zmiennych @INCpo PERL5LIBi PERLLIBzmiennych środowiskowych, zadziałają, uruchom 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 opcja wiersza poleceń

    Perl wstępnie oczekuje @INCna listę katalogów (oddzielonych dwukropkami) przekazanych jako wartość -Iopcji wiersza poleceń. Można to zrobić na trzy sposoby, jak zwykle z opcjami Perla:

    • Przekaż to w wierszu poleceń:

      perl -I /my/moduledir your_script.pl
    • Przekaż go przez pierwszą linię (shebang) skryptu Perla:

      #!/usr/local/bin/perl -w -I /my/moduledir
    • Przekaż jako część PERL5OPT(lub PERLOPT) zmiennej środowiskowej (patrz rozdział 19.02 w Programowaniu w Perlu )

  3. Przekaż to poprzez libpragmę

    Perl uprzednio oczekuje na przesłanie @INCdo niego listy katalogów use lib.

    W programie:

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

    W wierszu poleceń:

    perl -Mlib=/dir1,/dir2

    Możesz także usunąć katalogi z @INCpoprzezno lib .

  4. Możesz bezpośrednio manipulować @INCjako zwykłą tablicę Perla.

    Uwaga: Ponieważ @INCjest używany podczas fazy kompilacji, należy to zrobić wewnątrz BEGIN {}bloku, który poprzedza use MyModuleinstrukcję.

    • Dodaj katalogi na początek za pośrednictwem unshift @INC, $dir.

    • Dodaj katalogi do końca za pośrednictwem push @INC, $dir.

    • Rób wszystko, co możesz zrobić z tablicą Perla.

Uwaga: katalogi są bez shiftu wychodzą @INCw kolejności podanej w tej odpowiedzi, np domyślnym @INCjest ostatni na liście, poprzedzony PERL5LIBpoprzedzone -I, poprzedzony use liboraz bezpośrednia @INCmanipulacja, to ostatnie dwa mieszane w zależności od tego kolejności są w kodzie Perl.

Bibliografia:

Wydaje się, że nie ma obszernego @INCpostu typu FAQ na temat przepełnienia stosu, więc to pytanie jest zamierzone jako jedno.

Kiedy stosować każde podejście?

  • Jeśli moduły w katalogu muszą być używane przez wiele / wszystkie skrypty w Twojej witrynie, zwłaszcza uruchamiane przez wielu użytkowników, katalog ten powinien zostać zawarty w domyślnej @INCkompilacji do pliku binarnego Perla.

  • Jeśli moduły w katalogu będą używane wyłącznie przez określonego użytkownika do wszystkich skryptów uruchamianych przez użytkownika (lub jeśli rekompilacja Perla nie jest opcją zmiany domyślnej @INCw poprzednim przypadku użycia), ustaw 'użytkowników' PERL5LIB, zwykle podczas logowania użytkownika.

    Uwaga: Należy pamiętać o zwykłych pułapkach zmiennych środowiskowych systemu Unix - np. W niektórych przypadkach uruchamianie skryptów, ponieważ dany użytkownik nie gwarantuje uruchomienia ich ze skonfigurowanym środowiskiem tego użytkownika, np su. Przez .

  • Jeśli moduły w katalogu muszą być używane tylko w określonych okolicznościach (np. Gdy skrypt (y) jest wykonywany w trybie programowania / debugowania, możesz ustawić PERL5LIBręcznie lub przekazać -Iopcję perl.

  • Jeśli moduły muszą być używane tylko do określonych skryptów, wszyscy użytkownicy ich używają, używają use lib/ no libpragma w samym programie. Należy go również używać, gdy katalog, który ma być przeszukiwany, musi być dynamicznie określany w czasie wykonywania - np. Na podstawie parametrów wiersza poleceń skryptu lub ścieżki skryptu ( bardzo ładny przypadek użycia znajduje się w module FindBin ).

  • Jeśli katalogami @INCnależy manipulować zgodnie z jakąś skomplikowaną logiką, albo niemożliwą, albo zbyt niewygodną do wdrożenia za pomocą kombinacji use lib/ no libpragm, należy użyć bezpośredniej @INCmanipulacji wewnątrz BEGIN {}bloku lub w bibliotece specjalnego przeznaczenia przeznaczonej do @INCmanipulacji, której musi użyć skrypt (s) przed użyciem jakichkolwiek innych modułów.

    Przykładem tego jest automatyczne przełączanie między bibliotekami w katalogach prod / uat / dev, z pobieraniem bibliotek kaskadowych w prod, jeśli brakuje go w dev i / lub UAT (ostatni warunek sprawia, że ​​standardowe rozwiązanie „use lib + FindBin” jest dość skomplikowane. szczegółowych ilustracji tego scenariusza jest w jaki sposób korzystać z modułów Perla beta beta skryptów Perl? .

  • Dodatkowym przypadkiem użycia do bezpośredniego manipulowania @INCjest możliwość dodania odwołań do podprogramów lub odwołań do obiektów (tak, Virginia, @INCmoże zawierać niestandardowy kod Perla, a nie tylko nazwy katalogów, jak wyjaśniono w rozdziale Kiedy wywoływane jest odwołanie do podprogramu w @INC? ).

DVK
źródło
1
nie zapomnij PERLOPT, w którym możesz ustawić -I. Ponadto, takie jak base.pm i local :: lib używają rzeczy, które wymieniłeś w sposób dorozumiany.
brian d foy
1
@brian - use :: base używa go z powodu „wymagania” pod spodem, IIRC. Nie znam lokalnego :: lib, będę musiał przeczytać więcej, aby zrozumieć o co chodzi
DVK
3
Ponadto, aby była to naprawdę dobra odpowiedź, musisz powiedzieć ludziom, kiedy powinni użyć każdego z nich. Danie im 10 opcji, w jaki sposób mogą to zrobić, nie jest zbyt pomocne. :)
brian d foy
PS Każdy, prosimy o edycję odpowiedzi w celu dołączenia drugiego katalogu specyficznego dla architektury poprzez -I / use lib. Planowałem to zrobić później, ale na razie muszę przejść do trybu offline.
DVK
@brian - dodał PERLOPT. Mam ochotę wspomnieć o base.pm i innych elementach, kiedy @INC się przyzwyczai.
DVK
18

Oprócz wymienionych powyżej lokalizacji, wersja Perla dla OS X ma również dwa inne sposoby:

  1. Plik /Library/Perl/x.xx/AppendToPath. Ścieżki wymienione w tym pliku są dołączane do @INC w czasie wykonywania.

  2. Plik /Library/Perl/x.xx/PrependToPath. Ścieżki wymienione w tym pliku są dodawane do @INC w czasie wykonywania.

dgatwood
źródło
6

Jak już powiedziano, @INC jest tablicą i możesz dowolnie dodawać.

Mój skrypt REST CGI wygląda następująco:

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

Brak podprogramu jest eksportowany przez Rest.pm.

Kacper Perschke
źródło