11

假设我有一个 Perl 文件,其中的某些部分只有在作为脚本调用时才需要运行。我记得以前读过有关将这些部分包含在 main() 方法中并执行

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

但我忘记了条件是什么。搜索谷歌并没有取得任何成果。有人可以指出寻找这个的正确位置吗?

4

3 回答 3

16

如果文件作为脚本调用,则不会有调用者,因此您可以使用:

main() unless caller;

参见brian d foy解释

#!/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
于 2009-07-15T13:45:32.093 回答
7

I call these things "modulinos" originally in my Scripts as Modules article for The Perl Journal (now Dr. Dobbs). Google that term and you get the right resources. Sinan already linked to my development sources for one of my books where I talk about it. You might also like How a Script Becomes a Module.

于 2009-07-15T23:05:47.367 回答
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(!@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');

在比上面的“运行”方法更大的交互式脚本中:

...
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 有插件;因此您可以轻松增加看到的调试输出量、在代码更改时重新启动应用程序、使应用程序持久化、在分析器中运行等)

于 2009-07-15T22:30:32.883 回答