In Perl, how can I find out if my file is being us

2019-01-18 12:50发布

Let's say I have a Perl file in which there are parts I need to run only when I'm called as a script. I remember reading sometime back about including those parts in a main() method and doing a

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

But I forgot what the condition was. Searching Google hasn't turned out anything fruitful. Can someone point out the right place to look for this?

3条回答
祖国的老花朵
2楼-- · 2019-01-18 13:08

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.

查看更多
疯言疯语
3楼-- · 2019-01-18 13:12

Better to not do this, and instead take a structured approach like MooseX::Runnable.

Your class will look like:

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;
    }
}

Now you have a class that can be used inside your program easily:

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

Inside an interactive script that is bigger than just the "run" method above:

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

If you just want to do this standalone, you can say:

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

Notice how little code you wrote, and how flexible the resulting class is. "main if !caller" is nice, but why bother when you can do better?

(BTW, MX::Runnable has plugins; so you can easily increase the amount of debugging output you see, restart your app when the code changes, make the app persistent, run it in the profiler, etc.)

查看更多
何必那么认真
4楼-- · 2019-01-18 13:15

If the file is invoked as a script, there will be no caller so you can use:

main() unless caller;

See 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"

Output:

C:\Temp> perl MyClass.pm
Hello World

Using from another script:

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

use strict;
use warnings;

use MyClass;

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

Output:

C:\Temp> mytest.pl
Hello World
查看更多
登录 后发表回答