2009-04-13 4 views
7

Ho iniziato a creare un pacchetto Perl che contiene un modello di posta elettronica predefinito.Un modulo Perl sa dove è installato?

il manifesto sembra qualcosa di simile:

SendMyEmail.pm 
SendMyEmail/defualt_email.tt 

Attualmente So dove il modulo (e il modello) sono - ma non il modulo stesso sa dove su disco è? Quindi il modulo potrebbe trovare il modello predefinito senza il mio aiuto?

# This is what I would like to do. 
package SendMyEmail; 
sub new { 
    my ($self, $template) = @_; 
    $template ||= $dir_of_SendMyEmail .'/SendMyEmail/default_email.tt'; # ?? 
} 

C'è un modo migliore di includere un testo di modelli o un luogo migliore per inserire il modello?

Qualsiasi riferimento a moduli CPAN che fanno qualcosa di simile sarebbe il benvenuto.

Grazie in anticipo.

+0

OK, io voto per chiudere la questione. Impossibile eliminarlo a causa di risposte in aumento. –

+0

Si noti che questi due commenti sopra sono da una domanda dupe che è stata ora unita a questa e in quanto tale non sono più accurate. – Ether

risposta

9

Ogni file perl ha accesso alla variabile __FILE__ che gli dice il suo percorso completo. Qualcosa del genere dovrebbe fare il trucco:

my $DEFAULT_TEMPLATE; 
BEGIN { 
    $DEFAULT_TEMPLATE = __FILE__; 
    $DEFAULT_TEMPLATE =~ s,\.pm$,/default_email.tt,; 
} 

Eppure, se invece si è di raggruppare i file di 'dati' con i moduli allora diano un'occhiata al File::ShareDir che fornisce un modo per farlo.

+0

__FILE__ è descritto in perldata. http://perldoc.perl.org/perldata.html – CoffeeMonster

2

riscritto per riflettere quello che ho imparato nei commenti:

  • trovare il percorso del modulo

    package FooBar; 
    
    use File::Spec; 
    sub location { 
    return File::Spec->rel2abs(__FILE__); 
    } 
    
  • Dove mettere il modello:

    Dal momento che il modello sarà molto probabilmente modificabile, forse anche da qualcuno che lavora in rete, I str consiglia vivamente di metterlo in una directory in cui il "codice" contenuto nel modello non può essere eseguito.

    Immaginate qualcuno che chiama: http://your.home.net/cgi-bin/default_email.tt

+0

FindBin ti darà solo la posizione dello script perl che è stato avviato (il file .pl) non la posizione del file che richiama FindBin. – potyl

+0

Buon punto! Ovviamente non ho letto la domanda abbastanza vicino! – lexu

+0

Purtroppo, __FILE__ non restituisce il percorso completo, "solo" il percorso relativo allo script, a quanto pare. Il libro dei cammelli (copia antica) non è specifico. – lexu

3

Perl registra anche la posizione del file nella variabile% INC. Puoi usarlo quando __FILE__ non è disponibile. Vedere la documentazione in perlvar per i dettagli.

5

È possibile utilizzare l'hash %INC se il modulo è già caricato. Per esempio:

## load the module 
use Data::Dumper; 

## output full path to Data::Dumper module loaded 
print $INC{'Data/Dumper.pm'}; 

## see which module was loaded (if you have multiple folders with same modules) 
print Dumper(\%INC); 
1

È possibile utilizzare il __FILE__ token per ottenere il nome (incluso il percorso) del file corrente. Se vuoi conoscere il percorso di un modulo diverso (uno già caricato) controlla il contenuto dell'hash %INC.

7

L'utilizzo di% INC può essere fuorviante nei casi in cui il file non corrisponde esattamente al nome del pacchetto. (Questo è un anti-pattern, ma succede, a volte per ragioni giustificabili.) Se si desidera individuare i file, il pratico token __FILE__ è la soluzione migliore.Modulo esempio che può individuare in sé:

package Foo::Bar; 

use Cwd qw(abs_path); 
use File::Basename qw(dirname); 

sub module_dir { abs_path(dirname(__FILE__)) } 

1; 

Usage:

use Foo::Bar; 

print Foo::Bar->module_dir, "\n"; 
+0

Questo non funzionerà per i moduli che non è possibile controllare –

+2

Il sottotipo di esempio nella domanda è denominato "findmyself" e utilizza '__PACKAGE__', quindi penso che il controllo di il modulo è un presupposto sicuro. –

1

Io uso questo alias bash per trovare la posizione di un modulo (ad esempio, a guardare la sua attuazione o di incidere in alcune dichiarazioni di stampa di debug):

perlwhere() { 
    perl -wle'eval "require $ARGV[0]" or die; ($mod = $ARGV[0]) =~ s|::|/|g; print $INC{"${mod}.pm"}' $1 
} 
 
$ perlwhere Test::More 
/usr/lib/perl5/5.8.8/Test/More.pm