我有一个 Perl 程序,它需要使用包(我也写)。其中一些包仅在运行时选择(基于某些环境变量)。当然,我不想在我的代码中为所有这些包添加一个“使用”行,但只有一个“使用”行,基于这个变量,比如:
use $ENV{a};
不幸的是,这当然行不通。关于如何做到这一点的任何想法?
在此先感谢,奥伦
eval "require $ENV{a}";
" use
" 在这里不能很好地工作,因为它只在eval
.
正如@Manni 所说,实际上,最好使用require。引自man perlfunc
:
如果 EXPR 是一个裸字,则 require 假定为“.pm”扩展名,并且 将文件名中的“::”替换为“/”,以便于 加载标准模块。这种形式的模块加载不 冒着改变你的命名空间的风险。 换句话说,如果你试试这个: 需要 Foo::Bar;# 一个精彩的裸词 require 函数实际上会寻找“Foo/Bar.pm”文件 在@INC 数组中指定的目录中。 但如果你试试这个: $class = 'Foo::Bar'; 需要$类;# $class 不是裸词 #或者 需要“Foo::Bar”;# 因为“”而不是一个裸词 require 函数将在@INC 中查找“Foo::Bar”文件 数组,并会抱怨在那里找不到“Foo::Bar”。在这个 你可以这样做: eval "需要 $class";
"use" 语句在编译时运行,而不是在运行时。您将需要 require 您的模块:
my $module = "Foo::Bar";
eval "require $module";
我会使用UNIVERSAL::require。它同时具有使用包的require和use方法。use方法还将调用包的导入。
use UNIVERSAL::require;
$ENV{a}->use or die 'Could not import package: ' . $@;
如果您不希望它在编译时发生,您可能想要使用require
而不是,然后手动导入您可能需要的任何符号。use
请参阅指向 Perl Cookbook(来自 Google 图书)的链接,以很好地讨论可用于实现所需目标的方法。
我认为在运行时加载的模块可以是插件。我有这种问题,某些情况下的特定模块在运行时作为带有Module::Pluggable的插件加载。
也许您需要更改模块的逻辑,但它可以很好地工作和扩展(我的应用程序从四个模块开始,现在有二十个,并且还在增长)。
如何使用核心模块Module::Load
用你的例子:
use Module::Load;
load $ENV{a};
“Module::Load - 模块和文件的运行时要求”
“加载消除了了解您是否尝试要求文件或模块的需要。”
如果它失败了,它会以类似"Can't locate xxx in @INC (@INC contains: ..."之类的东西而死。
许多年后,eval "use $mod_name";
似乎工作得很好(至少从 5.8.8 开始)。
优点eval "require $mod_name";
是加载模块的默认导出是自动导入的;换句话说:
eval "use $mod_name";
是较短的等价物
eval "require $mod_name"; $mod_name->import();
这是一个测试命令,它通过 env 传递模块的名称。variable mod_name
,加载并导入模块,然后使用导入的函数(假设是类似 POSIX 的 shell):
$ mod_name='Data::Dumper' perl -e 'eval "use $ENV{mod_name}"; print Dumper("hi!")'
$VAR1 = 'hi!';
我可能遗漏了细微之处;如果是这样,请告诉我。