Come è costruito @INC di Perl?(ovvero quali sono tutti i modi per influenzare il luogo in cui vengono cercati i moduli Perl?)
-
22-09-2019 - |
Domanda
Quali sono tutti i modi che influenzano il luogo in cui vengono cercati i moduli Perl?O, Come è costruito @INC di Perl?
Come sappiamo, Perl utilizza @INC
array contenente i nomi delle directory per determinare dove cercare i file dei moduli Perl.
Non sembra esserci un post completo di tipo FAQ "@INC" su StackOverflow, quindi questa domanda è intesa come tale.
Soluzione
Vedremo come il contenuto di questo array è costruito e come può essere manipolato per influenzare dove l'interprete Perl troverà i file del modulo.
Predefinito
@INC
L'interprete Perl lo è compilato con uno specifico
@INC
valore di default.Per scoprire questo valore, eseguienv -i perl -V
comando (env -i
ignora ilPERL5LIB
variabile 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 directory dello script).Manca in Perl 5.26+ e quando Perl viene eseguito 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
Variabile ambientale
PERL5LIB
(OPERLLIB
)Perl è pre-pendente
@INC
con un elenco di directory (separate da due punti) contenute inPERL5LIB
(se non è definito,PERLLIB
viene utilizzata) variabile d'ambiente della tua shell.Per vedere il contenuto di@INC
DopoPERL5LIB
EPERLLIB
le variabili di ambiente hanno avuto effetto, eseguiperl -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 .
-I
opzione della riga di comandoPerl è pre-pendente
@INC
con un elenco di directory (separate da due punti) passato come valore di-I
opzione della riga di comando.Questo può essere fatto in tre modi, come al solito con le opzioni Perl:Passalo dalla riga di comando:
perl -I /my/moduledir your_script.pl
Passalo tramite la prima riga (shebang) del tuo script Perl:
#!/usr/local/bin/perl -w -I /my/moduledir
Passalo come parte di
PERL5OPT
(OPERLOPT
) variabile d'ambiente (vedi capitolo 19.02 in Programmazione Perl)
Passalo tramite il
lib
pragmaPerl è pre-pendente
@INC
con un elenco di directory passate ad esso tramiteuse lib
.In un programma:
use lib ("/dir1", "/dir2");
Sulla riga di comando:
perl -Mlib=/dir1,/dir2
Puoi anche rimuovere le directory da
@INC
attraversono lib
.Puoi manipolare direttamente
@INC
come un normale array Perl.Nota:Da
@INC
viene utilizzato durante la fase di compilazione, questa deve essere fatta all'interno di aBEGIN {}
blocco, che precede iluse MyModule
dichiarazione.Aggiungi directory all'inizio tramite
unshift @INC, $dir
.Aggiungi directory alla fine tramite
push @INC, $dir
.Fai qualsiasi altra cosa che puoi fare con un array Perl.
Nota:Le directory sono immutabile su @INC
nell'ordine elencato in questa risposta, ad es.predefinito @INC
è l'ultimo dell'elenco, preceduto da PERL5LIB
, preceduto da -I
, preceduto da use lib
e diretto @INC
manipolazione, gli ultimi due mescolati nell'ordine in cui si trovano nel codice Perl.
Riferimenti:
- perldoc perlmod
- perldoclib
- Perl Module Mechanics: un'ottima guida contenente pratici how-to
- Come faccio a "usare" un modulo Perl in una directory non in
@INC
? - Programmazione Perl - capitolo 31 parte 13, cap 7.2.41
- Come fa un programma Perl a sapere dove trovare il file contenente il modulo Perl che utilizza?
Non sembra esserci una soluzione completa @INC
Post di tipo FAQ su Stack Overflow, quindi questa domanda è intesa come tale.
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 nell'impostazione predefinita
@INC
compilato nel binario Perl.Se i moduli nella directory saranno usati esclusivamente da un utente specifico per tutti gli script che l'utente esegue (o se ricompilare Perl nonèun'opzione per cambiare le impostazioni predefinite
@INC
nel caso d'uso precedente), impostare gli utentiPERL5LIB
, solitamente durante l'accesso dell'utente.Nota:Si prega di essere consapevoli delle solite insidie delle variabili di ambiente Unix, ad es.in alcuni casi l'esecuzione degli script come un particolare utente non garantisce la loro esecuzione con l'ambiente di quell'utente configurato, ad es.attraverso
su
.Se i moduli nella directory devono essere utilizzati solo in circostanze specifiche (es.quando gli script vengono eseguiti in modalità sviluppo/debug, è possibile impostare
PERL5LIB
manualmente o passare il file-I
opzione perl.Se i moduli devono essere utilizzati solo per script specifici, by Tutto gli utenti che li utilizzano, utilizzano
use lib
/no lib
pragma nel programma stesso.Dovrebbe essere utilizzato anche 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 file TrovaBin modulo per un caso d'uso molto interessante).Se le directory in
@INC
devono essere manipolati secondo una logica complicata, impossibile o troppo ingombrante da implementare mediante una combinazione diuse lib
/no lib
pragma, quindi utilizzare direct@INC
manipolazione all'internoBEGIN {}
blocco o all'interno di una libreria per scopi speciali designata per@INC
manipolazione, che deve essere utilizzata dai tuoi script prima che venga utilizzato qualsiasi altro modulo.Un esempio di ciò è il passaggio automatico tra le librerie nelle directory prod/uat/dev, con il prelievo della libreria a cascata in prod se manca da dev e/o UAT (l'ultima condizione rende la soluzione standard "usa lib + FindBin" piuttosto complicata.Un'illustrazione dettagliata di questo scenario è disponibile in Come posso utilizzare i moduli Perl beta dagli script Perl beta?.
Un ulteriore caso d'uso per la manipolazione diretta
@INC
è poter aggiungere riferimenti a subroutine o riferimenti a oggetti (sì, Virginia,@INC
può contenere codice Perl personalizzato e non solo nomi di directory, come spiegato in Quando viene chiamato un riferimento a una subroutine in @INC?).
Altri suggerimenti
In aggiunta alle posizioni di cui sopra, la versione OS X di Perl ha anche altri due modi:
-
Il file /Library/Perl/x.xx/AppendToPath. Percorsi elencati in questo file vengono aggiunti alla @INC in fase di esecuzione.
-
Il file /Library/Perl/x.xx/PrependToPath. Percorsi elencati in questo file sono preceduti da @INC in fase di esecuzione.
Come è stato detto già @INC è un array e tu sei libero di aggiungere tutto quello che vuoi.
Il mio script CGI REST appare come:
#!/usr/bin/perl
use strict;
use warnings;
BEGIN {
push @INC, 'fully_qualified_path_to_module_wiht_our_REST.pm';
}
use Modules::Rest;
gone(@_);
subroutine passata viene esportato dal Rest.pm.