2010-03-26 12 views
13

Se il mio programma Perl utilizza moduli Perl, come determinerà dove trovare il file contenente il codice del modulo?Come fa un programma Perl a sapere dove trovare il file contenente il modulo Perl che usa?

Per esempio, se il programma contiene:

use MyModule1;    # Example 1 
use This::Here::MyModule2; # Example 2 

dove sarà?

+0

Non riuscivo a trovare una risposta esaustiva a questa domanda su SO a cui potevo collegarmi, quindi ho deciso di crearne uno. Se la risposta fornita di seguito ha bisogno di aggiunte/correzioni, si prega di avere a questo :) – DVK

risposta

13

Perl interpreter (che esegue il programma perl) utilizzerà uno speciale array denominato @INC per cercare un file contenente il modulo.

Ogni valore nell'array @INC è un nome di directory (ma vedere la nota sotto); Perl cercherà all'interno di quelle directory in un ciclo utilizzando le regole specificate di seguito. (Si prega di fare riferimento a this SO post for details of how the contents of @INC are determined).

Se il file del modulo non viene trovato dopo aver esaurito @INC, la compilazione del programma viene interrotta con un errore. Se il file del modulo viene trovato in una delle directory specificate in @INC, la ricerca è terminata senza guardare il resto di @INC.

Il modo in cui Perl cerca un file modulo all'interno di ciascuna delle directory elencate nella @INC è la seguente:

  • In primo luogo, sarà separare le componenti gerarchici del nome del modulo (parole separate da ::), in ultimo componente - che verrà utilizzato per formare un nome file - e un percorso gerarchico (tutti i componenti precedenti l'ultimo ::).

    Nel caso in cui il nome del modulo abbia un solo componente (no ::, ad esempio MyModule1 sopra), il percorso della gerarchia è vuoto e il nome file è il nome del modulo. Nel secondo esempio di questa domanda, l'ultimo componente è MyModule2 e il percorso della gerarchia sarà This::Here.

  • Il nome del file previsto verrà determinato aggiungendo l'ultimo componente del nome del modulo con un'estensione .pm. Per esempio. MyModule1.pm e MyModule2.pm nei nostri esempi.

    NOTA: i nomi dei moduli sono ovviamente sensibili alla distinzione tra maiuscole e minuscole su Unix e altri sistemi operativi in ​​cui la denominazione di file/directory fa distinzione tra maiuscole e minuscole.

  • directory del modulo sarà determinato da:

    1. Prendendo la directory successiva da @INC - diciamo /usr/lib/perl come esempio

    2. Formare una sottodirectory di quella directory prendendo la gerarchia percorso del nome del modulo (se presente) e sostituzione di "::" con / o qualsiasi altro carattere che il sistema operativo utilizza come separatore di directory. Nei nostri due esempi, il primo modulo verrà cercato in /usr/lib/perl (nessuna sottodirectory) e il secondo in /usr/lib/perl/This/Here.

    3. NOTA: quanto sopra è una leggera semplificazione - @INCmay also contain subroutine references and object references, che caricare i moduli come il loro codice personalizzato specifica invece di eseguire la ricerca nella directory come specificato nel # 2 logica sopra. Questa funzionalità sembra essere utilizzata raramente e in questo articolo si presuppone che l'intero @INC contenga solo le directory.

Andiamo su un esempio specifico, partendo dal presupposto che il vostro @INC contiene due sub-directory: ("/usr/lib/perl", "/opt/custom/lib").

Poi Perl cercherebbe come segue:

 
========================================================================== 
| Module    | Try # | File to try    
========================================================================== 
| MyModule1    | Try 1 | /usr/lib/perl/MyModule1.pm 
| MyModule1    | Try 2 | /opt/custom/lib/MyModule1.pm 
========================================================================== 
| This::Here::MyModule2 | Try 1 | /usr/lib/perl/This/Here/MyModule2.pm 
| This::Here::MyModule2 | Try 2 | /opt/custom/lib/This/Here/MyModule2.pm 
========================================================================== 

Si prega di ricordare che Perl interprete smettere di cercare di cercare una volta che trova il file in una delle posizioni, senza cercare di capire se il file è in posizioni successive anche. Per esempio. se esiste /usr/lib/perl/This/Here/MyModule2.pm, allora Perl non cercherà, né si preoccuperà dell'esistenza, di /opt/custom/lib/This/Here/MyModule2.pm.

NOTA: @INC viene utilizzato ogni volta interprete Perl utilizza require -come meccanismo per l'importazione moduli Perl. Ciò include:

  • require direttiva stessa
  • use MyModule economico (equivalente a richiedere + import)
  • use base (equivalente a richiedere + "push @ISA")
+2

Vale probabilmente la pena di notare da dove proviene il contenuto di @INC. Questo potrebbe anche essere la risposta che l'OP stava cercando. Il breve riassunto: I contenuti predefiniti principali sono integrati (i dettagli esatti dei percorsi dipendono dall'installazione, ovviamente). I modi principali per modificarlo al di fuori dello script sono impostare la variabile d'ambiente PERL5LIB (un elenco di percorsi delimitato da due punti) o fornire le opzioni '-I/path/to/dir' all'eseguibile in fase di runtime. (Questi antepongono all'array) – Cascabel

+0

Chiunque ha un bel elenco autorevole di come viene costruito @INC? Quello in perldoc perlvar sembra mancare qualsiasi menzione di PERL5LIB, così come il meccanismo '$ Config {sitelib}/sitecustomize.pl' (che deve essere compilato in fase di compilazione). – Cascabel

+0

@DVK: eccellente! Erroneamente presume che tu sia stato fatto a causa del commento alla domanda e del fatto che questo è già incredibilmente accurato. – Cascabel

2

Secondo il perlfunc documentation on use:

utilizzare Modulo LI ST

Importa alcune semantiche nel pacchetto corrente dal modulo denominato, in genere facendo l'alias di alcuni subroutine o nomi di variabili nel pacchetto. È esattamente equivalente a

BEGIN { require Module; Module->import(LIST); } 

eccetto che il modulo deve essere un bareword.

Così require fa il sollevamento di carichi pesanti, e il require documentation fornisce

Se ESPR è un bareword, la richiedono assume un'estensione ".pm" e sostituisce "::" con "/" nel nome del file per voi, per rendere più facile per caricare moduli standard. Questa forma di caricamento dei moduli non rischia di alterare il tuo spazio dei nomi.

In altre parole, se si tenta questo:

require Foo::Bar; # a splendid bareword 

La funzione require cercherà in realtà il file "Foo/Bar.pm" nelle directory specificate nella matrice @INC.

5

Sebbene questo non risponda direttamente alla domanda, ecco alcune semplici tecniche per determinare il percorso completo del file del modulo che si desidera utilizzare.

Per visualizzare il contenuto di default della matrice @INC, insieme a un sacco di altre informazioni, dalla riga di comando:

perl -V  

Se si desidera conoscere la posizione del modulo Carp:

perldoc -l Carp 

All'interno di uno script, la stampa del contenuto dell'hash %INC è utile per determinare il modulo effettivo che si sta utilizzando, specialmente se è stato modificato @INC dal valore predefinito:

use Carp; 
print $INC{'Carp.pm'}; 

Questo semplice script può essere utilizzato anche per Find installed Perl modules matching a regular expression e di individuare eventuali moduli duplicati in diverse directory.

+0

@toolic - questa risposta è strettamente legato alla Domanda OP, ma ritengo che sia in qualche modo separata da essa (ad esempio "da dove viene il modulo che ho importato"). Ti dispiacerebbe neanche la pubblicazione come un Q separata + A su SO (mi collego ad esso), o dandomi il tuo consenso a chiedere come Q separata e pubblicare la tua risposta (o avermi permesso di pubblicare il vostro)? – DVK

+0

fatto! http://stackoverflow.com/questions/2527990/how-do-i-find-which-file-taintain-perl-module-my-script-uses – DVK

+0

@DVK - Se ho due versioni di perl nel mio percorso di Windows variabile di ambiente, quindi come fa il sistema a sapere quale perl scegliere? È il primo? Ho diversi perls per diversi software installati sulla mia macchina. Sono stati installati insieme al software. – stack1

Problemi correlati