Come è costruito @INC di Perl? (aka Quali sono tutti i modi per influenzare la ricerca dei moduli Perl?)


199

Quali sono tutti i modi per influenzare la ricerca dei moduli Perl? oppure, come è costruito @INC di Perl ?

Come sappiamo, Perl utilizza un @INCarray contenente nomi di directory per determinare dove cercare i file del modulo Perl .

Non sembra esserci un post completo di tipo FAQ "@INC" su StackOverflow, quindi questa domanda è da intendersi come una sola.


7
Sì, ma ce n'è uno perfettamente valido su search.cpan.org/perldoc/… ?
mob,

3
@mobrule: non penso che sia così completo - sta solo dicendo come aggiungere @INCin fase di esecuzione, non la costruzione completa.
Cascabel,

2
@mobrule - @Jefromi ha indovinato a destra - il problema principale con QUALUNQUE e tutti i riferimenti che ho trovato finora era la mancanza di informazioni complete sul default compilato di perl binary @INC
DVK

3
Alcuni possono rendere tale risposta esaustiva inviandomi una patch. È facile perché perlfaq è in Github. :)
brian d foy il

1
Bene, le "informazioni complete su @INC predefinito compilato di perl binary" sono che è quello che la persona che l'ha compilato ha impostato. Se stai chiedendo dei vari percorsi che vi arrivano, penso che tu abbia una domanda diversa da quella a cui hai risposto.
brian d foy,

Risposte:


254

Vedremo come sono costruiti i contenuti di questo array e possono essere manipolati per influenzare dove l'interprete Perl troverà i file del modulo.

  1. Predefinito @INC

    L'interprete Perl è compilato con un @INCvalore predefinito specifico . Per scoprire questo valore, esegui il env -i perl -Vcomando ( env -iignora la PERL5LIBvariabile ambientale - vedi # 2) e nell'output vedrai qualcosa del genere:

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

Nota .alla fine; questa è la directory corrente (che non è necessariamente la stessa della directory dello script). Manca in Perl 5.26+ e quando Perl funziona con -T(controlli di contaminazione abilitati) .

Per modificare il percorso predefinito durante la configurazione della compilazione binaria Perl, impostare l'opzione di configurazione otherlibdirs:

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

  1. Variabile ambientale PERL5LIB(o PERLLIB)

    Perl è in attesa @INCdi un elenco di directory (separate da due punti) contenute nella variabile d'ambiente PERL5LIB(se non è definita PERLLIB) della shell. Per vedere i contenuti di @INCafter PERL5LIBePERLLIB variabili environment hanno avuto effetto, esegui 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 opzione da riga di comando

    Perl è in sospeso @INCcon un elenco di directory (separate da due punti) passate come valore -Idell'opzione della riga di comando. Questo può essere fatto in tre modi, come al solito con le opzioni Perl:

    • Passalo sulla riga di comando:

      perl -I /my/moduledir your_script.pl
    • Passalo attraverso la prima riga (shebang) del tuo script Perl:

      #!/usr/local/bin/perl -w -I /my/moduledir
    • Passalo come parte della PERL5OPT(o PERLOPT) variabile d'ambiente (vedi capitolo 19.02 in Programmazione Perl )

  3. Passalo attraverso il libpragma

    Perl anticipa @INC con un elenco di directory passate ad esso tramite use lib.

    In un programma:

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

    Sulla riga di comando:

    perl -Mlib=/dir1,/dir2

    Puoi anche rimuovere le directory da @INCviano lib .

  4. Puoi manipolare direttamente @INC come un normale array Perl.

    Nota: poiché @INCviene utilizzato durante la fase di compilazione, questo deve essere fatto all'interno di un BEGIN {}blocco, che precede iluse MyModule istruzione.

    • Aggiungi directory all'inizio tramite unshift @INC, $dir .

    • Aggiungi le directory alla fine tramite push @INC, $dir.

    • Fai qualsiasi altra cosa tu possa fare con un array Perl.

Nota: Le directory sono unshifted sul @INCnell'ordine elencato in questa risposta, ad esempio, di default @INCè l'ultima nella lista, preceduto da PERL5LIB, preceduta da -I, preceduto dause lib e diretta @INCmanipolazione, gli ultimi due mescolato in qualsiasi ordine in cui sono in codice Perl.

Riferimenti:

Non sembra essere un completo @INC post di tipo FAQ su StackTranslate.it, quindi questa domanda è da intendersi come una sola.

Quando utilizzare ciascun approccio?

  • Se i moduli in una directory devono essere utilizzati da molti / tutti gli script sul tuo sito, in particolare eseguiti da più utenti, quella directory dovrebbe essere inclusa nel predefinito @INCcompilato nel binario Perl.

  • Se i moduli nella directory verranno utilizzati esclusivamente da un utente specifico per tutti gli script eseguiti dall'utente (o se la ricompilazione di Perl non è un'opzione per modificare il valore predefinito @INCnel caso d'uso precedente), impostare gli utenti PERL5LIB, di solito durante l'accesso dell'utente.

    Nota: si prega di essere consapevoli delle solite insidie ​​della variabile d'ambiente Unix - ad es. In alcuni casi l'esecuzione degli script in quanto un determinato utente non garantisce l'esecuzione con l'impostazione dell'ambiente dell'utente, ad es su. Tramite .

  • Se i moduli nella directory devono essere utilizzati solo in circostanze specifiche (ad es. Quando gli script vengono eseguiti in modalità di sviluppo / debug, è possibile impostare PERL5LIBmanualmente o passare l' -Iopzione a perl.

  • Se i moduli devono essere utilizzati solo per script specifici, da parte di tutti gli utenti che li utilizzano, utilizzare use lib/ no libpragmas nel programma stesso. Dovrebbe anche essere usato quando la directory da cercare deve essere determinata dinamicamente durante il runtime, ad es. Dai parametri della riga di comando dello script o dal percorso dello script (vedere il modulo FindBin per un caso d'uso molto piacevole).

  • Se le directory in questione @INCdevono essere manipolate secondo una logica complicata, impossibile o troppo ingombrante da implementare mediante la combinazione di use lib/ no libpragmas, utilizzare la @INCmanipolazione diretta all'interno del BEGIN {}blocco o all'interno di una libreria per scopi speciali designata per@INC manipolazione, che deve essere utilizzata dallo script (s) prima di utilizzare qualsiasi altro modulo.

    Un esempio di questo è il passaggio automatico tra librerie nelle directory prod / uat / dev, con pickup della libreria waterfall in prod se manca da dev e / o UAT (l'ultima condizione rende la soluzione standard "usa lib + FindBin" abbastanza complicata. illustrazione dettagliata di questo scenario è in Come faccio a utilizzare i moduli Perl beta da script Perl beta? .

  • Un ulteriore caso d'uso per la manipolazione diretta @INCè quello di poter aggiungere riferimenti a subroutine o riferimenti a oggetti (sì, Virginia, @INCpuò contenere codice Perl personalizzato e non solo nomi di directory, come spiegato in Quando viene chiamato un riferimento a subroutine in @INC? ).


1
non dimenticare PERLOPT, dove è possibile impostare -I. Inoltre, cose come base.pm e local :: lib usano le cose che hai elencato implicitamente.
brian d foy,

1
@brian - use :: base lo usa per "richiedere" sotto, IIRC. Non ho familiarità con local :: lib, dovrò leggere di più per capire di cosa si tratta
DVK

3
Inoltre, per rendere questa una risposta davvero buona, devi dire alle persone quando dovrebbero usarle. Dare loro 10 opzioni su come potrebbero non è molto utile. :)
brian d foy,

PS Chiunque, non esitate a modificare la risposta per includere una seconda inclusione della directory specifica dell'architettura tramite -I / use lib. Ho pianificato di farlo da solo in un secondo momento, ma per ora ho bisogno di rimanere offline.
DVK,

@brian - aggiunto PERLOPT. Ho voglia di menzionare base.pm e altri elementi "quando viene utilizzato @INC" è più adatto alle domande frequenti sui file del modulo @ INC / find che ho pubblicato e collegato da qui, quindi l'ho messo lì.
DVK,

18

Oltre alle posizioni sopra elencate, la versione OS X di Perl ha anche altri due modi:

  1. Il file /Library/Perl/x.xx/AppendToPath. I percorsi elencati in questo file vengono aggiunti a @INC in fase di esecuzione.

  2. Il file /Library/Perl/x.xx/PrependToPath. I percorsi elencati in questo file sono anteposti a @INC in fase di runtime.


6

Come già detto, @INC è un array e sei libero di aggiungere tutto ciò che desideri.

Il mio script REST CGI è simile a:

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

La subroutine andata viene esportata da Rest.pm.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.