如何使用仅在运行时知道的Perl包?

时间:2009-01-14 12:02:49

标签: perl runtime packages require

我有一个Perl程序,需要使用包(我也写)。其中一些软件包仅在运行时选择(基于某些环境变量)。当然,我不想在我的代码中为所有这些包添加“使用”行,但只有一个“使用”行,基于此变量,如下所示:

use $ENV{a};

不幸的是,这当然不起作用。关于如何做到这一点的任何想法?

提前致谢, 奥伦

7 个答案:

答案 0 :(得分:8)

eval "require $ENV{a}";

use”在这里效果不佳,因为它只会在eval的上下文中导入。

正如@Manni所说,实际上,最好使用require。引自man perlfunc

If EXPR is a bareword, the require assumes a ".pm" extension and 
replaces "::" with "/" in the filename for you, to make it easy to 
load standard modules.  This form of  loading of modules does not 
risk altering your namespace.

In other words, if you try this:

        require Foo::Bar;    # a splendid bareword

The require function will actually look for the "Foo/Bar.pm" file 
in the directories specified in the @INC array.

But if you try this:

        $class = 'Foo::Bar';
        require $class;      # $class is not a bareword
    #or
        require "Foo::Bar";  # not a bareword because of the ""

The require function will look for the "Foo::Bar" file in the @INC 
array and will complain about not finding "Foo::Bar" there.  In this 
case you can do:

        eval "require $class";

答案 1 :(得分:8)

“use”语句在编译时运行,而不是在运行时运行。您需要改为使用模块:

my $module = "Foo::Bar";
eval "require $module";

答案 2 :(得分:6)

我会使用UNIVERSAL::require。它具有 require use 方法来使用包。 use 方法也会为包调用 import

use UNIVERSAL::require;
$ENV{a}->use or die 'Could not import package:  ' . $@;

答案 3 :(得分:4)

如果您不希望它在编译时发生,您可能希望使用require而不是use,然后手动导入您可能需要的任何符号。有关可用于实现目标的方法的详细讨论,请参阅this link to the Perl Cookbook(来自Google图书)。

答案 4 :(得分:4)

我认为在运行时加载的模块可以是插件。我遇到了这类问题,在某些情况下使用特定模块作为插件Module::Pluggable在运行时加载。

也许您需要更改模块的逻辑,但它的工作和扩展性非常好(我的应用程序以四个模块开始,现在有二十个,并且它正在增长)。

答案 5 :(得分:3)

如何使用核心模块Module::Load

用你的例子:

use Module::Load;
load $ENV{a};

“Module :: Load - 运行时需要模块和文件”

“加载无需知道您是要求文件还是模块。”

如果失败,它将会死于类似的东西“无法在@INC中找到xxx(@INC包含:......”

答案 6 :(得分:1)

多年以后,eval "use $mod_name";似乎工作正常(截至至少5.8.8)。

优于eval "require $mod_name";的优点是加载模块的默认导出自动导入;换句话说:

eval "use $mod_name";

的较短等价物

eval "require $mod_name"; $mod_name->import();

这是一个测试命令,它通过env传递模块的名称。变量mod_name,加载和导入模块,然后使用导入的函数(假设类似POSIX的shell):

 $ mod_name='Data::Dumper' perl -e 'eval "use $ENV{mod_name}"; print Dumper("hi!")'
 $VAR1 = 'hi!';

我可能会遗漏微妙之处;如果是的话,请告诉我。