Как в Perl узнать, используется ли мой файл как модуль или как сценарий?

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

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

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


person sundar - Remember Monica    schedule 15.07.2009    source источник


Ответы (3)


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

main() unless caller;

См. brian d foy -as-modules / 184416165 "rel =" nofollow noreferrer "> объяснение.

#!/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
person Sinan Ünür    schedule 15.07.2009
comment
Это действительно полезно. Спасибо за ссылку. - person seth; 15.07.2009
comment
А что насчет perl -MMyClass -e' ... '? - person Brad Gilbert; 16.07.2009
comment
@Brad Gilber Когда MyClass.pm написан таким образом, perl MyClass.pm делает то же самое, что и perl -MMyClass -e 'main()' - person Sinan Ünür; 16.07.2009

Изначально я назвал эти вещи «модулями» в своей статье Скрипты как модули для Perl Journal (теперь Доктор Доббс). Погуглите этот термин, и вы получите нужные ресурсы. Синан уже связался с моими источниками разработки для одной из моих книг, где я говорю об этом. Вам также может понравиться Как сценарий становится модулем.

person brian d foy    schedule 15.07.2009

Лучше не делать этого и вместо этого использовать структурированный подход, например 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(!@data){
            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');

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

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

Обратите внимание, как мало вы написали кода и насколько гибким является получившийся класс. "main if! caller" - это хорошо, но зачем беспокоиться, если можно сделать лучше?

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

person jrockway    schedule 15.07.2009
comment
+1 за указание лося. Я до сих пор не вложился в это мышление. - person Sinan Ünür; 16.07.2009