使用eval加载模块

时间:2011-07-28 08:21:46

标签: perl module load runtime eval

我在使用Perl和内置函数eval时遇到了一些麻烦。 我浏览了网页,但找不到任何答案或示例代码。

我想动态加载模块(在执行时间之前我不知道它们)

$module_name="Auth_Auth_Test";
my $ret1;
ret = eval{
     "use ".$module_name;
     $ret1 = $module_name."::test(".$log.")";
};              
$log->debug ($@) if $@;
$log->debug ("Ret".$ret1);

回报是:

  

RetAuth_Auth_Test ::测试(自定义:: LOG = HASH(0x1194468))

以下方法对我有用,但我无法加载多个具有相同子程序的模块:

my $use = "use ".$module_name." qw(&test)";
$ret = eval $use;

# Debug for eval
$log->debug ($@) if $@;

$ret = test($log);

感谢您的帮助

3 个答案:

答案 0 :(得分:4)

改为使用Module::Load

答案 1 :(得分:2)

我强烈建议你使用Class::Load,由于穆斯的依赖性,它现在无处不在:

use Class::Load qw(:all);

my $module = 'Web::Spider::' . $module;
try_load_class($module)
    or warn "unable to load '$module'";

这是一个广泛的解释,说明为什么它比Module :: Load更好(尽管后来成为Perl核心的一部分):http://blog.fox.geek.nz/2010/11/searching-design-spec-for-ultimate.html

TL; DR:

  

Perl 5.8功能(现在在5.10中解决)的一个怪癖是,一旦需要一个模块,只要该文件存在于磁盘上,$ INC {}将被更新以将模块名称映射到找到的文件名。这看起来并不坏,直到你看到它在其他地方被再次调用的行为方式。

Class :: Load解决了这个问题。 Module :: Load没有。

答案 2 :(得分:1)

在第一个片段中,

"use ".$module_name;

仅被评估为字符串。这是因为字符串eval和块eval之间存在差异。有关这些文档之间的差异,请参阅eval文档。

您可以使用以下内容:

use strict; use warnings;

my $module_name = "Auth_Auth_Test";
eval "require $module_name";
if($@) {
    warn "Could not load module: $@\n";
}
my $ret = $module_name->test("params");
print "return $ret\n";

但无论如何,daxim的建议是合理的,你可能不想重新发明已经用perl分发的东西。自{5.3.4以来Module::Load处于核心地位。