代码之家  ›  专栏  ›  技术社区  ›  Sundar R

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

  •  10
  • Sundar R  · 技术社区  · 17 年前

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

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

    但我忘了是什么情况。搜索谷歌并没有取得任何成果。有人能指出合适的地方找这个吗?

    3 回复  |  直到 11 年前
        1
  •  15
  •   Community Mohan Dere    9 年前

    如果将文件作为脚本调用,则不会 caller 所以你可以使用:

    main() unless caller;
    

    brian d foy 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
    
        2
  •  7
  •   brian d foy    17 年前

    我最初在我的 Scripts as Modules 文章为 Perl期刊 (现在) 多布斯博士 )谷歌这个词,你就能得到正确的资源。Sinan已经和我的一本书的开发资源联系在了一起,我在书中谈到了它。你也可能喜欢 How a Script Becomes a Module .

        3
  •  2
  •   jrockway    17 年前

    最好不要这样做,而是采取一种结构化的方法,比如 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>
    

    注意您编写的代码有多少,结果类有多灵活。”主若是!打电话的人“很好,但你能做得更好,为什么还要费心呢?

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