如何在不使用 eval 的情况下动态包含 Perl 模块?
我需要动态包含 Perl 模块,但如果可能的话,由于工作编码标准,我希望远离 eval。这是可行的:
$module = "My::module";
eval("use $module;");
但如果可能的话,我需要一种无需 eval
即可完成此操作的方法。所有 google 搜索都会导致 eval
方法,但不会以任何其他方式进行。
是否可以在没有eval
的情况下做到这一点?
I need to dynamically include a Perl module, but if possible would like to stay away from eval due to work coding standards. This works:
$module = "My::module";
eval("use $module;");
But I need a way to do it without eval
if possible. All google searches lead to the eval
method, but none in any other way.
Is it possible to do it without eval
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
使用
require
在运行时加载模块。将其包装在块(而不是字符串)eval
中通常是一个好主意,以防模块无法加载。使用
eval {...} 或 do {...}
语法并复制$@
的原因是$@
是一个全局变量,可以由许多不同的事物设置。您希望尽可能以原子方式获取该值,以避免其他因素将其设置为不同值的竞争条件。如果您直到运行时才知道模块的名称,则必须手动在模块名称 (My::Module) 和文件名 (My/Module.pm) 之间进行转换:
Use
require
to load modules at runtime. It often a good idea to wrap this in a block (not string)eval
in case the module can't be loaded.The reason for the
eval {...} or do {...}
syntax and making a copy of$@
is because$@
is a global variable that can be set by many different things. You want to grab the value as atomically as possible to avoid a race condition where something else has set it to a different value.If you don't know the name of the module until runtime you'll have to do the translation between module name (My::Module) and file name (My/Module.pm) manually:
如何使用核心模块 Module::Load
以您的示例:
“Module::Load - 两者的运行时要求模块和文件”
“加载使您无需知道您是否需要文件或模块。”
如果失败,它将因类似“无法在 @INC 中定位 xxx(@INC 包含:...”)而终止。
How about using the core module Module::Load
With your example:
"Module::Load - runtime require of both modules and files"
"load eliminates the need to know whether you are trying to require either a file or a module."
If it fails it will die with something of the like "Can't locate xxx in @INC (@INC contains: ...".
好吧,总是有
require
如注意,你会失去任何东西您可能会从编译时而不是运行时调用
import
中获得效果。编辑:此方法和 eval 方法之间的权衡是:eval 允许您使用正常的模块语法,并在模块名称无效(而不是仅仅找不到)时给出更明确的错误。 OTOH,eval 方式(可能)更容易受到任意代码注入的影响。
Well, there's always
require
as inNote that you lose whatever effects you may have gotten from the
import
being called at compile time instead of runtime.Edit: The tradeoffs between this and the eval way are: eval lets you use the normal module syntax and gives you a more explicit error if the module name is invalid (as opposed to merely not found). OTOH, the eval way is (potentially) more subject to arbitrary code injection.
不,没有eval
是不可能的,因为require()
需要裸字模块名称,如perldoc -f require。然而,这并不是对 eval 的恶意使用,因为它不允许注入任意代码(当然,假设您可以控制您需要的文件的内容)。编辑: 代码已修改如下,但为了完整性,我保留第一个版本。
我使用我曾经使用这个小糖模块在运行时进行动态加载:PS。我盯着这个定义(我很久以前写的),我正在考虑添加这个:
$class->export_to_level(1, undef, @imports);
...它应该工作,但未经测试。编辑:现在是版本 2,无需评估就好多了(感谢 ysth)::)
No, it's not possible to withouteval
, asrequire()
needs the bareword module name, as described at perldoc -f require. However, it's not an evil use of eval, as it doesn't allow injection of arbitrary code (assuming you have control over the contents of the file you arerequire
ing, of course).EDIT: Code amended below, but I'm leaving the first version up for completeness.
I useI used to use this little sugar module to do dynamic loads at runtime:PS. I'm staring at this definition (I wrote it quite a while ago) and I'm pondering adding this:
$class->export_to_level(1, undef, @imports);
... it should work, but is not tested.EDIT: version 2 now, much nicer without an eval (thanks ysth): :)
CPAN 上的 Class::MOP 有一个 load_class 方法:
http://metacpan.org/pod/Class::MOP
Class::MOP on CPAN has a load_class method for this:
http://metacpan.org/pod/Class::MOP
我喜欢做这样的事情:
require Win32::Console::ANSI if ( $^O eq "MSWin32" );
i like doing things like..
require Win32::Console::ANSI if ( $^O eq "MSWin32" );