2009-07-15 27 views
10

Giả sử tôi có tệp Perl trong đó có các phần tôi cần để chạy chỉ khi tôi được gọi là tập lệnh. Tôi nhớ đọc đôi khi về việc bao gồm các phần đó trong phương thức main() và thực hiện một sốTrong Perl, làm cách nào để tìm hiểu xem tệp của tôi có đang được sử dụng làm mô-đun hay chạy dưới dạng tập lệnh không?

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

Nhưng tôi đã quên điều kiện là gì. Tìm kiếm Google đã không bật ra bất cứ điều gì hiệu quả. Ai đó có thể chỉ ra đúng nơi để tìm kiếm điều này?

Trả lời

15

Nếu tập tin được gọi là một kịch bản, sẽ không có caller vì vậy bạn có thể sử dụng:

main() unless caller; 

Xem 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 

Sử dụng từ kịch bản khác:

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 
+0

Điều này thực sự hữu ích. Cảm ơn các liên kết. – seth

+0

@seth bạn được chào đón. –

+0

Điều gì về 'perl -MMyClass -e '...''? –

2

Tốt hơn để không làm điều này, và thay vào đó lấy một cách tiếp cận có cấu trúc như MooseX::Runnable.

lớp của bạn sẽ trông giống như:

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([email protected]){ 
      say "No data found for $for_person"; 
      return 1; 
     } 

     for my $data (@data){ 
      say $data->format; 
     } 

     return 0; 
    } 
} 

Bây giờ bạn có một lớp có thể được sử dụng bên trong chương trình của bạn một cách dễ dàng:

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

Bên trong một kịch bản tương tác lớn hơn chỉ là "chạy "phương pháp trên:

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

Nếu bạn chỉ muốn thực hiện việc này độc lập, bạn có thể nói:

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

Lưu ý bạn viết mã nhỏ như thế nào và lớp linh hoạt như thế nào. "chính nếu! người gọi" là tốt đẹp, nhưng tại sao bận tâm khi bạn có thể làm tốt hơn?

(BTW, MX :: Runnable có plugin; vì vậy bạn có thể dễ dàng tăng số lượng đầu ra gỡ lỗi bạn thấy, khởi động lại ứng dụng của bạn khi mã thay đổi, làm cho ứng dụng liên tục, chạy trong hồ sơ, v.v.)

+0

+1 để hiển thị một cách Moose.Tôi vẫn chưa đầu tư để có được suy nghĩ đó. –

7

Tôi gọi những điều này là "modulinos" ban đầu trong bài viết Scripts as Modules của tôi cho Tạp chí Perl (bây giờ là Tiến sĩ Dobbs). Google thuật ngữ đó và bạn có được các nguồn lực phù hợp. Sinan đã liên kết với các nguồn phát triển của tôi cho một trong những cuốn sách của tôi, nơi tôi nói về nó. Bạn cũng có thể thích How a Script Becomes a Module.

Các vấn đề liên quan