问题
Is there a way to load entire modules during runtime in Perl? I had thought I found a good solution with autouse
but the following bit of code fails compilation:
package tryAutouse2;
use autouse 'tryAutouse';
my $obj = tryAutouse->new();
I imagine this is because autouse
is specifically meant to be used with exported functions, am I correct? Since this fails compilation, is it impossible to have a packaged solution? Am I forced to require
before each new module invocation if I want dynamic loading?
The reasoning behind this is that my team loads many modules, but we're afraid this is eating up memory.
回答1:
You want Class::Autouse or ClassLoader.
Due to too much magic, I use ClassLoader only in my REPL for convenience. For serious code, I always load classes explicitely. Jack Maney points out in a comment that Module::Load and Module::Load::Conditional are suitable for delayed loading.
回答2:
There's nothing wrong with require IMO. Skip the export of the function and just call the fully qualified name:
require Some::Module;
Some::Module::some_function(@some_arguments);
回答3:
eval 'use tryAutouse; 1;' or die $@;
Will work. But you might want to hide the ugliness.
回答4:
When you say:
use Foo::Bar;
You're loading module Foo::Bar
in at compile time. Thus, if you want to load your module in at run time, you'd use require
:
require Foo::Bar;
They are sort of equivalent, but there are differences. See the Perldoc on use to understand the complete difference. For example, require
used in this way won't automatically load in imported functions. That might be important to you.
If you want to test whether a module is there or not, wrap up your require
statement in an eval
and test whether or not eval
is successful.
I use a similar technique to see if a particular Perl module is available:
eval { require Mail::Sendmail; };
if ($@) {
$watch->_Send_Email_Net_SMTP($watcher);
return;
}
In the above, I'll attempt to use Mail::Sendmail
which is an optional module if it's available. If not, I'll run another routine that uses 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: You need to use curly braces around your eval
statement and not parentheses. Otherwise, if the require
doesn't work, your program will exit which is probably not what you want to do.
回答5:
Instruction 'use' is performed at compile time, so check the path to the module also takes place at compile time. This may cause incorrect behavior, which are difficult to understand until you consider the contents of the @INC array.
One solution is to add block 'BEGIN', but the solution shown below is inelegant.
BEGIN { unshift @INC, '/path/to/module/'; }
use My::Module;
You can replace the whole mess a simple directive:
use lib '/path/to/module';
use My::Module;
This works because it is performed at compile time. So everything is ready to execute 'use' instruction.
Instead of the 'BEGIN' block, you can also decide to different instruction executed at compile time ie declaring a constant.
use constant LIB_DIR => '/path/to/module';
use lib LIB_DIR;
use My::Module;
来源:https://stackoverflow.com/questions/9470019/load-perl-modules-automatically-during-runtime-in-perl