【发布时间】:2010-10-01 08:37:09
【问题描述】:
我有一个 Perl 程序,它需要使用包(我也写)。其中一些包仅在运行时选择(基于某些环境变量)。当然,我不想在我的代码中为所有这些包添加一个“使用”行,但只有一个“使用”行,基于这个变量,比如:
use $ENV{a};
很遗憾,这当然行不通。关于如何做到这一点的任何想法?
提前致谢, 奥伦
【问题讨论】:
标签: perl runtime packages require
我有一个 Perl 程序,它需要使用包(我也写)。其中一些包仅在运行时选择(基于某些环境变量)。当然,我不想在我的代码中为所有这些包添加一个“使用”行,但只有一个“使用”行,基于这个变量,比如:
use $ENV{a};
很遗憾,这当然行不通。关于如何做到这一点的任何想法?
提前致谢, 奥伦
【问题讨论】:
标签: perl runtime packages require
eval "require $ENV{a}";
“use”在这里不能很好地工作,因为它只在 eval 的上下文中导入。
正如@Manni 所说,实际上,最好使用require。引用man perlfunc:
【讨论】:
"use" 语句在编译时运行,而不是在运行时。您将需要 require 您的模块:
my $module = "Foo::Bar";
eval "require $module";
【讨论】:
我会使用UNIVERSAL::require。它同时具有 require 和 use 方法来使用一个包。 use 方法也会为包调用 import。
use UNIVERSAL::require;
$ENV{a}->use or die 'Could not import package: ' . $@;
【讨论】:
如果您不希望在编译时发生这种情况,您可能希望使用require 而不是use,然后手动导入您可能需要的任何符号。请参阅this link to the 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 传递模块的名称。变量mod_name,加载并导入模块,然后使用导入的函数(假设是类似POSIX的shell):
$ mod_name='Data::Dumper' perl -e 'eval "use $ENV{mod_name}"; print Dumper("hi!")'
$VAR1 = 'hi!';
我可能遗漏了一些细节;如果有,请告诉我。
【讨论】: