2009-07-15 1 views
10

Предположим, у меня есть файл Perl, в котором есть части, которые мне нужно запускать, только когда я вызывается как скрипт. Я помню, как читал некоторое время назад о включении этих частей в качестве основного метода() и делатьВ Perl, как я могу узнать, используется ли мой файл в качестве модуля или запускается как сценарий?

main() unless(<some condition which tests if I'm being used as a module>); 

Но я забыл, что условие было. Поиск Google не принес ничего плодотворного. Может ли кто-нибудь указать подходящее место для поиска?

ответ

15

Если файл вызывается в качестве сценария, будет не caller, так что вы не можете использовать:

main() unless caller; 

См brian d foy «s explanation.

#!/usr/bin/perl 

use strict; 
use warnings; 

main() unless caller; 

sub main { 
    my $obj = MyClass->new; 
    $obj->hello; 
} 

package MyClass; 

use strict; 
use warnings; 

sub new { bless {} => shift }; 

sub hello { print "Hello World\n" } 

no warnings 'void'; 
"MyClass" 

Выход:

C:\Temp> perl MyClass.pm 
Hello World 

Использование другого скрипта:

C:\Temp\> cat mytest.pl 
#!/usr/bin/perl 

use strict; 
use warnings; 

use MyClass; 

my $obj = MyClass->new; 
$obj->hello; 

Выход:

C:\Temp> mytest.pl 
Hello World 
+0

Это действительно полезно. Спасибо за ссылку. – seth

+0

@seth добро пожаловать. –

+0

Как насчет 'perl -MMyClass -e '...''? –

2

Лучше не делать этого, и вместо того, чтобы принять структурированный подход, как MooseX::Runnable.

Ваш класс будет выглядеть следующим образом:

class Get::Me::Data with (MooseX::Runnable, MooseX::Getopt) { 

    has 'dsn' => (
     is   => 'ro', 
     isa   => 'Str', 
     documentation => 'Database to connect to', 
    ); 

    has 'database' => (
     is   => 'ro', 
     traits  => ['NoGetopt'], 
     lazy_build => 1, 
    ); 

    method _build_database { 
     Database->connect($self->dsn); 
    } 

    method get_data(Str $for_person){ 
     return $database->search({ person => $for_person }); 
    } 

    method run(Str $for_person?) { 
     if(!$defined $for_person){ 
      print "Type the person you are looking for: "; 
      $for_person = <>; 
      chomp $for_person; 
     } 

     my @data = $self->get_data($for_person); 

     if([email protected]){ 
      say "No data found for $for_person"; 
      return 1; 
     } 

     for my $data (@data){ 
      say $data->format; 
     } 

     return 0; 
    } 
} 

Теперь у вас есть класс, который может быть использован в вашей программе легко:

my $finder = Get::Me::Data->new(database => $dbh); 
$finder->get_data('jrockway'); 

Внутри интерактивный сценарий, который больше, чем просто «бега "выше:

... 
my $finder = Get::Me::Data->new(dsn => 'person_database'); 
$finder->run('jrockway') and die 'Failure'; # and because "0" is success 
say "All done with Get::Me::Data."; 
... 

Если вы просто хотите сделать это отдельно, вы можете сказать:

$ mx-run Get::Me::Data --help 
Usage: mx-run ... [arguments] 
    --dsn  Database to connect to 

$ mx-run Get::Me::Data --dsn person_database 
Type the person you are looking for: jrockway 
<data> 

$ mx-run Get::Me::Data --dsn person_database jrockway 
<data> 

Обратите внимание, как мало кода вы написали и насколько гибким является результирующий класс. «главное, если!», приятно, но зачем беспокоиться, когда вы можете сделать лучше?

(BTW, MX :: Runnable имеет плагины, поэтому вы можете легко увеличить количество отладочного вывода, которое вы видите, перезапустить приложение, когда код изменяется, сделать приложение постоянным, запустить его в профилировщике и т. Д.)

+0

+1 для показа Муз-пути.Я все еще не сделал инвестиции, чтобы проникнуть в этот образ мышления. –

7

Я называю эти вещи "modulinos" первоначально в моей статье Scripts as Modulesдля The Perl Journal (теперь доктор Доббс). Google этот термин, и вы получаете нужные ресурсы. Синан уже связан с моими источниками развития одной из моих книг, где я об этом говорю. Вам также может понравиться How a Script Becomes a Module.