2012-03-24 124 views
2

我一直在用modulino perl模式進行操作,並且想要在不知道軟件包名稱的情況下加載一個模塊,而只知道它所在的文件。我正在尋找可以這樣使用的東西:加載並使用perl模塊而不知道模塊名稱,但知道文件名

eval { 
    my $file = "some-file-name-in-the-hierarchy-unrelated-to-package-name"; 
    my $module = something($file); 
    $module->sub1(); 
}; 

something這裏是關鍵。否requireuse,因爲之後我需要模塊名稱。我必須閱讀$file並解析package名稱才能使用它嗎?我確定可能有更好的方法。總是存在於perl中。

+0

如果你甚至不知道你正在嘗試使用的模塊名稱,你怎麼知道有'sub1'? – cjm 2012-03-24 04:58:46

+1

你爲什麼試圖這樣做?你只是好奇,還是你有充分的理由? – 2012-03-24 07:34:08

+0

原因是我使用modulinos作爲腳本和模塊。操作的實際名稱由文件名錶示,而不是包名稱。 – rmarimon 2012-03-24 13:40:06

回答

5

你控制哪些文件?如果您正在創建程序爲modulino,然後嘗試加載該文件,只需使文件中的最後一個語句返回程序包名稱即可。 require希望您返回一個真正的值,大多數模塊使用1;。但是,您可以使用任何您喜歡的真實值。這將是require返回值:

# i_dont_know_whats_inside 
package Buster; 

__PACKAGE__; 

加載很容易:

my $package = require 'i_dont_know_whats_inside'; 

print "Package is $package\n"; 

$package->new(...); 

如果你無法控制你加載該文件,它並不難找出裏面有什麼:

my @packages = load_file('i_dont_know_whats_inside'); 

print "Packages are @packages\n"; 

sub load_file { 
    my $file = shift; 
    require Module::Extract::Namespaces; 
    my @packages = Module::Extract::Namespaces->from_file($file); 
    my $rc = require $file; 
    return @packages; 
    } 
+0

嘗試了兩種方法,他們的工作就像一個魅力。因爲它比返回'1;'更簡單並且不遜色。 – rmarimon 2012-03-24 14:01:29

+0

布賴恩我在語句'__PACKAGE __;'的行得到錯誤'在void context中無用的常量'。關於如何擺脫此警告的任何想法。 – rmarimon 2012-03-24 17:11:05

+0

當你到達那裏時關閉警告,或者你可以做一個任務。分配的結果是您分配的值。 :) – 2012-03-24 17:15:30

0

不知道包是否意味着信息必須由加載機制返回,這意味着我們需要使用do

使用do表示我們不能使用符號表,這意味着匿名潛艇。

創建一個看起來像下面這樣的文件:

sub foo { ... } 
sub bar { ... } 

{ 
    foo => \&foo, 
    bar => \&bar, 
}; 

或類似

{ 
    foo => sub { ... }, 
    bar => sub { ... }, 
}; 

然後使用

my $table = do '/abs/path/to/file.pl' or die [email protected]; 
$table{foo}->(); 

my $table = do 'rel/path/to/file.pl' or die [email protected]; # Relative to entries in @INC 
$table{foo}->(); 

您可以多次調用do,但要避免它,因爲它每次編譯和運行文件。相反,緩存它返回的值。

UGLY!而所有這些都是因爲你不希望文件名和其中的包之間有任何關係。如果你試圖繞過Perl的要求,期待醜陋。它甚至不幫你有這個要求,所以擺脫它。

什麼應該做的,而不是爲創建一個看起來像下面這樣的文件:

package Some::Package; 

sub foo { shift; ... } 
sub bar { shift; ... } 

1; 

調用代碼將是:

my $file= 'Some/Package.pm'; 
my $pkg = $file; 
$file =~ s{\.pm\z}{}; 
$file =~ s{/}{::}g; 

require $file; 
$pkg->foo(); 

Module::PluginFinder見。

+0

@rmarimon,答案已更新。 (完全重寫) – ikegami 2012-03-24 00:49:28

+0

「需要做」有點強。你可以這樣做,但你不需要「。 – 2012-03-24 07:33:29

+0

在這種情況下,調用代碼需要包名「Some :: Package」,這正是我試圖避免的。 – rmarimon 2012-03-24 13:42:19

0

require中的文字(和變量)完全解釋爲文件名。

例如:

$var = "TEST::test"; 
require $var; 

輸出:

Can't locate TEST::test in @INC (@INC contains: ...) 
      ^^^^^^^^^^ -- not TEST/test.pm! 
相關問題