Domanda Come può il mio script Perl trovare il suo modulo nella stessa directory?


Recentemente ho scritto un nuovo script Perl per uccidere i processi in base al nome del processo / nome utente e lo ho esteso usando Classes in modo da poter riutilizzare il codice di processo in altri programmi. Il mio layout attuale è -

/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 sto usando è la direttiva use lib in questo modo -

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

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


MODIFICARE

  1. Ho scelto la risposta "depesz" come quella corretta a causa della sua semplicità e del suo utilizzo del modulo principale.
  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.

44
2018-04-08 05:17


origine


risposte:


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

use FindBin;
use lib $FindBin::Bin;

In genere, preferisco che i miei script siano forniti in modo tale che i programmi siano in qualunque cosa / bin, e le librerie siano in qualsiasi cosa / lib

In queste situazioni uso un approccio leggermente più complicato:

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

La chiamata abs_path è di fare in modo che @INC contenga qualunque cosa / lib, e non qualunque / bin /../ lib - è solo un piccolo cambiamento, ma rende più facile leggere i messaggi di errore.


46
2018-04-08 06:32



Sono curioso di sapere perché la soluzione semplicistica

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

non è venuto. 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 nel documentazione. Non l'ho davvero testato.

Per avere qualsiasi altro percorso relativo alla posizione di questo file Perl, fai qualcosa di simile

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

45
2017-09-16 14:37



A partire dal perlfaq8, che risponde "Come aggiungo una directory al mio percorso di inclusione (@INC) in fase di esecuzione?". Ci sono molte altre risposte alle domande su questo problema.


Come aggiungo una directory al mio percorso di inclusione (@INC) in fase di runtime?

Ecco i modi suggeriti per modificare il percorso di inclusione, comprese le variabili di ambiente, le opzioni di runtime e le istruzioni nel codice:

la variabile d'ambiente PERLLIB

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

la variabile d'ambiente PERL5LIB

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

il flag perl -Idir della riga di comando

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

l'uso di lib pragma:

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

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


9
2018-04-08 14:58



Dare un'occhiata a 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. Vedere Module :: Starterper un modo semplice per creare tutti i file necessari per creare una distribuzione in stile CPAN standard.


3
2018-04-08 05:29



Puoi fare in modo che perl guardi in qualsiasi directory usando il -I bandiera. Qui, -I sta per @INC che è l'array di percorsi in cui perl cerca i moduli. utilizzando -I aggiunge il percorso indicato al @INC array per questa esecuzione.

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


1
2017-10-12 15:12



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.


0
2018-04-09 02:11



FindBin :: librerie troverà tutte le tue librerie posizionate in posizioni ragionevoli rispetto al percorso da cui il tuo script è in esecuzione.


-1
2017-09-10 14:52



Basta che sia semplice. Non è necessario importare alcuna libreria; scopri la tua attuale directory di lavoro:

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

Per problemi simili, puoi leggere la variabile di ambiente che fornisce le tue informazioni su dove ti trovi, la tua home directory, il sistema operativo e così via, con solo una riga di codice di programmazione nel terminale di shell, come:

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

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


-1
2018-02-01 14:00