在Perl中,如何确定我的文件是用作模块还是作为脚本运行?

时间:2009-07-15 13:10:07

标签: perl module modulino

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

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

但我忘记了病情。搜索Google并没有发现任何有益的结果。有人能指出正确的地方寻找这个吗?

3 个答案:

答案 0 :(得分:15)

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

main() unless caller;

请参阅brian d foyexplanation

#!/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

答案 1 :(得分:7)

我最初在我的Scripts as Modules文章中为 The Perl Journal (现在是 Dr.Dobbs )称这些东西为“modulinos”。谷歌那个词,你得到了合适的资源。思南已经把我的一本书的开发资料与我谈到了。您可能也喜欢How a Script Becomes a Module

答案 2 :(得分: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');

在一个比上面的“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>

注意你编写的代码很少,以及结果类的灵活性。 “主要的if!来电者”很不错,但为什么你能做得更好呢?

(BTW,MX :: Runnable有插件;因此您可以轻松增加所看到的调试输出量,在代码更改时重新启动应用程序,使应用程序持久化,在分析器中运行等等)