2009-04-08 9 views
40

Recentemente ho scritto un nuovo script Perl per uccidere i processi in base al nome del processo/nome utente e lo ho esteso utilizzando Classes in modo da poter riutilizzare il codice di processo in altri programmi. Il mio layout corrente è -Come può il mio script Perl trovare il suo modulo nella stessa directory?

/home/mutew/src/prod/pskill  <-- Perl script 
/home/mutew/src/prod/Process.pm <-- Package to handle process descriptions 

ho aggiunto ~/src/prod nella mia variabile $ PATH per accedere allo script da qualsiasi luogo. L'esecuzione dello script da qualsiasi directory diversa dalla sua directory residente porta a "Impossibile trovare Process.pm in @INC" (che è comprensibile dato che oltre alle directory condivise in/usr, @INC include solo la directory corrente - ''). Una soluzione alternativa che ho utilizzato è la direttiva use lib in questo modo -

use lib '/home/mutew/src/prod'; 

ma questo è un problema di portabilità principale. Qualche soluzione che mi consenta anche di esportare lo script su altri sistemi senza e modifiche?


EDIT

  1. ho scelto risposta 'depesz' come quella corretta per la sua semplicità e nucleo uso del modulo.
  2. La risposta di brian d foy suggerisce però altri metodi per realizzare lo stesso (TMTOWTDI), il suo contributo in perlfaq8 rende questa domanda assolutamente ridondante.
+0

forse è solo la mia installazione, ma se entrambi i file si trovano nella stessa directory, semplicemente "uso FILENAME.pm". Quindi "my $ newVar = PACKAGENAME-> new();" per qualsiasi programmazione di oggetti. –

+0

Wow, questo dovrebbe essere molto più facile in Perl di questo! Semplifica le cose, ecc. –

risposta

42

L'approccio più semplice l'ho trovato per utilizzare il modulo FindBin. Come questo:

use FindBin; 
use lib $FindBin::Bin; 

In generale io preferisco avere il mio script forniti in modo tale che i programmi si trovano in qualunque/bin e le librerie sono in qualunque/lib

In queste situazioni io uso un po 'più complicato approccio:

use Cwd qw(abs_path); 
use FindBin; 
use lib abs_path("$FindBin::Bin/../lib"); 

chiamata L'abs_path è quello di rendere il @INC contiene tutto ciò/lib, e non tutto ciò che/bin /../ lib - è solo un leggero cambiamento, ma rende la lettura dei messaggi di errore più facile.

+3

Non dimenticare che abs_path restituisce risultati contaminati in modalità contaminazione. Devi usare 'use lib (abs_path (" $ FindBin :: Bin /../ lib ") = ~ m {^ (/.*)}) [0];' o usa semplicemente 'use lib" $ FindBin :: Bin /../ lib ";" perché non c'è motivo di canonizzare il percorso. –

3

Dai uno sguardo allo Par::Packer. Crea un eseguibile con tutte le dipendenze dello script incluse. Rende facile la distribuzione. È inoltre possibile fornire agli utenti una versione del modulo che può essere installata sui propri sistemi. Vedi Module::Starter per un modo semplice per creare tutti i file necessari per creare una distribuzione in stile CPAN standard.

9

Da perlfaq8, che risponde a "How do I add a directory to my include path (@INC) at runtime?". Ci sono molte altre risposte alle domande su questo problema.


Come si aggiunge una directory al percorso di inclusione (@INC) in fase di esecuzione?

Ecco i modi suggerito di modificare il percorso di inclusione, tra le variabili di ambiente, interruttori a run-time, e in-codice dichiarazioni:

l'ambiente PERLLIB variabile

$ export PERLLIB=/path/to/my/dir 
$ perl program.pl 

l'ambiente PERL5LIB variabile

$ export PERL5LIB=/path/to/my/dir 
$ perl program.pl 

bandiera perl -Idir riga di comando

$ perl -I/path/to/my/dir program.pl 

la direttiva use lib:

use lib "$ENV{HOME}/myown_perllib"; 

L'ultimo è particolarmente utile perché conosce macchina architetture dipendenti. Il modulo pragmatico lib.pm è stato incluso per la prima volta nella versione 5.002 di Perl.

+0

Ho letto perlfaq8 più tardi lo stesso giorno e ho trovato la risposta che mi serviva nel tuo articolo. Mi chiedo perché hai incluso il secondo metodo (usa Cwd) anche se @INC ha già una voce per la directory corrente - '.' – aks

0

Per convertire i collegamenti relativi in ​​assoluto e aggiungere a @INC, normalmente utilizzo ex :: lib. Naturalmente, ciò è utile solo se si intende mantenere identiche le posizioni relative dello script e del modulo su tutte le macchine su cui si prevede di eseguire lo script.

38

io sono curioso di sapere perchè la soluzione semplicistica

use File::Basename; 
use lib dirname (__FILE__); 
use SomeModuleLocatedInTheSameDirectoryAsThisPerlScriptOrModule; 

non è venuto in su. Il modulo FindBin sembra avere alcuni problemi se il file non è lo script perl principale eseguibile, ma semplicemente un modulo Perl non eseguibile. Almeno è così che interpreto il commento nello documentation. Non l'ho davvero testato.

per avere un qualsiasi altro percorso relativo alla posizione di questo file Perl, fare qualcosa di simile

use File::Basename; 
use lib dirname (__FILE__) . "/MyModules"; 
+3

Mi piace molto questo approccio - ho solo dovuto usare 'usa Cwd qw (abs_path); usa lib dirname (abs_path (__ FILE __)); 'per rendere lo script callable tramite un link simbolico. Saluti! – sdaau

+0

Questa è l'unica risposta che ha funzionato –

+0

impressionante! Funziona! –

-1

FindBin::libs troveranno tutte le vostre librerie messe a luoghi ragionevoli relativi al percorso da dove lo script è in esecuzione.

-1

Basta che sia semplice. Non è necessario importare alcuna libreria; basta scoprire la directory di lavoro corrente:

use lib "$ENV{PWD}/relativ_path_own_perllib"; 

Per problemi simili, è possibile leggere la variabile d'ambiente che fornisce tutte le informazioni su dove siete, la vostra directory home, roba del sistema operativo, e così via, con un solo riga di codice di programmazione nel terminale di shell, ad esempio:

perl -e 'map { print; print " : ". $ENV{$_}." \n\r"; } sort keys %ENV ' 

Non è necessario associare alcune librerie; basta usare lo %ENV-Hash.

+0

'$ ENV {PWD}' non risolve il problema, al contrario. Restituisce la directory di lavoro di _user, non la posizione dello script. – pipe

0

È possibile effettuare il look perl in qualsiasi directory utilizzando il flag -I. Qui, -I sta per @INC che è l'array di percorsi in cui perl cerca i moduli. L'utilizzo di -I aggiunge il percorso specificato all'array @INC per questa esecuzione.

esempio:

perl -I lib bin/script.pl 

dove lib contiene i moduli che voglio usare.

So che questo funziona per perl 5. Non sono sicuro delle altre versioni.

Problemi correlati