Load perl modules automatically during runtime in Perl

老子叫甜甜 提交于 2020-01-15 06:34:44

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!