有没有办法在运行时在Perl中加载整个模块?我以为我找到了autouse
的一个很好的解决方案但是下面的代码无法编译:
包tryAutouse2;
使用autouse'tryAutouse';
我的$ obj = tryAutouse-> new();
我想这是因为autouse
专门用于导出函数,我是否正确?由于编译失败,是不可能有一个打包的解决方案?如果我想要动态加载,我会在每次新模块调用之前强制require
吗?
这背后的原因是我的团队加载了很多模块,但我们担心这会占用内存。
答案 0 :(得分:5)
您需要Class::Autouse或ClassLoader。
由于魔法太多,为方便起见,我只在我的REPL中使用ClassLoader。对于严肃的代码,我总是明确地加载类。 Jack Maney在评论中指出Module::Load和Module::Load::Conditional适合延迟加载。
答案 1 :(得分:4)
要求IMO没有任何问题。跳过函数的导出,只需调用完全限定名称:
require Some::Module;
Some::Module::some_function(@some_arguments);
答案 2 :(得分:1)
eval 'use tryAutouse; 1;' or die $@;
会工作吗?但你可能想隐藏丑陋。
答案 3 :(得分:1)
当你说:
use Foo::Bar;
您正在编译时加载模块Foo::Bar
。因此,如果要在运行时加载模块,则使用require
:
require Foo::Bar;
它们等同于,但存在差异。请参阅use上的Perldoc以了解完全不同之处。例如,以这种方式使用的require
将不会自动加载导入的函数。这对你来说很重要。
如果您想测试模块是否存在,请在require
中包含eval
语句,并测试eval
是否成功。
我使用类似的技术来查看特定的Perl模块是否可用:
eval { require Mail::Sendmail; };
if ($@) {
$watch->_Send_Email_Net_SMTP($watcher);
return;
}
在上面,我将尝试使用Mail::Sendmail
,如果它可用,它是一个可选模块。如果没有,我将运行另一个使用Net::SMTP
的例程:
sub _Send_Email_Net_SMTP {
my $self = shift;
my $watcher = shift;
require Net::SMTP; #Standard module: It should be available
WORD O'WARNING :您需要在eval
语句周围使用花括号而不是括号。否则,如果require
不起作用,您的程序将退出,这可能不是您想要做的。
答案 4 :(得分:1)
指令'use'在编译时执行,因此检查模块的路径也在编译时进行。这可能会导致错误的行为,在您考虑@INC数组的内容之前很难理解。
一种解决方案是添加块'BEGIN',但下面显示的解决方案不够优雅。
BEGIN { unshift @INC, '/path/to/module/'; }
use My::Module;
你可以用一个简单的指令替换整个混乱:
use lib '/path/to/module';
use My::Module;
这是有效的,因为它是在编译时执行的。所以一切都准备好执行'使用'指令。
您可以决定在编译时执行不同的指令,而不是'BEGIN'块,即声明一个常量。
use constant LIB_DIR => '/path/to/module';
use lib LIB_DIR;
use My::Module;