如何在不使用eval的情况下动态包含Perl模块?

use*_*723 27 perl module eval

我需要动态地包含一个Perl模块,但是如果可能的话,由于工作编码标准,我希望远离eval.这有效:

$module = "My::module";
eval("use $module;");
Run Code Online (Sandbox Code Playgroud)

但是eval如果可能的话,我需要一种方法来做到这一点.所有谷歌搜索都会导致该eval方法,但没有任何其他方式.

没有可能eval吗?

Mic*_*man 48

用于require在运行时加载模块.如果eval无法加载模块,通常最好将其包装在一个块(而不是字符串)中.

eval {
    require My::Module;
    My::Module->import();
    1;
} or do {
   my $error = $@;
   # Module load failed. You could recover, try loading
   # an alternate module, die with $error...
   # whatever's appropriate
};
Run Code Online (Sandbox Code Playgroud)

究其原因,eval {...} or do {...}语法和制作的副本$@,因为$@是可以通过许多不同的事情来设置一个全局变量.您希望尽可能原子地获取值,以避免竞争条件,其他东西已将其设置为不同的值.

如果您在运行时之前不知道模块的名称,则必须手动执行模块名称(My :: Module)和文件名(My/Module.pm)之间的转换:

my $module = 'My::Module';

eval {
    (my $file = $module) =~ s|::|/|g;
    require $file . '.pm';
    $module->import();
    1;
} or do {
    my $error = $@;
    # ...
};
Run Code Online (Sandbox Code Playgroud)

  • `s @'| :: @/@ g` - 对于歇斯底里的葡萄干,```和`::`可以作为包分隔符互换. (3认同)
  • 任何使用`'`作为JAPH之外的包分隔符的人都应该让代码中断. (3认同)
  • @Ether:你说这不安全(在编辑之前)是对的,但它与线程无关. (2认同)

Dav*_*idG 16

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

用你的例子:

use Module::Load;
my $module = "My::module";
load $module;
Run Code Online (Sandbox Code Playgroud)

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

"负载消除了你是否需要知道是否需要文件或模块的需要."

如果它失败了它会死于类似"无法在@INC中找到xxx(@INC包含:......").


Dan*_*Dan 10

嗯,总是require如此

require 'My/Module.pm';
My::Module->import();
Run Code Online (Sandbox Code Playgroud)

请注意,您import在编译时而不是运行时调用可能会失去的任何效果.

编辑:这与eval方式之间的权衡是:eval允许您使用普通模块语法,如果模块名称无效(而不是仅仅找不到),则会给出更明确的错误.OTOH,eval方式(可能)更容易受到任意代码注入.