如何在运行时在Perl中加载不在INC中的模块?

时间:2014-04-03 16:04:24

标签: perl perl-module

如何在Perl中加载不在@INC中的路径的模块?

我已经阅读了有关如何添加@INC路径的答案,但问题是必须在代码开头更改@INC。编译完成后,我遇到的所有模块都会查找@INC以查找模块的位置。我的问题是我们试图将所有这些环境特定的东西分离到配置文件中。如果它在配置文件中,则需要先读取路径才能将其推送到@INC,但是代码已经编译好了,似乎无法修改@INC。

  1. 有办法吗?是否有一个库可以让我加载一个模块并传递一个自定义路径?
  2. 这是一件可怕的坏事吗?为什么?

3 个答案:

答案 0 :(得分:8)

Perl有一个增量编译模型,这意味着可以在解析其他代码之前执行代码。为此,我们可以使用阶段块(又名。阶段):

BEGIN {
    print "This is executed as soon as the block has been parsed\n";
}

这样的相位块也可用于加载配置文件。

例如,use语句实际上是BEGIN块的语法糖。

use Foo::Bar qw/baz qux/;

相当于

BEGIN {
    require Foo::Bar; # or: require "Foo/Bar.pm";
    Foo::Bar->import(qw/baz qux/);
}

我们也可以在运行时加载模块,尽管这只适用于面向对象的模块。

所以我们有三个选择:

  1. BEGIN阶段加载配置,并在加载实际模块之前添加正确的库路径
  2. BEGIN期间手动加载模块及其完整路径(例如require "/my/modules/Foo/Bar.pm"
  3. 在运行时找出配置,然后加载模块。
  4. 使用裸require相当不舒服,这就是Module::Runtime存在的原因

答案 1 :(得分:3)

使用BEGIN块加载您的自定义@INC位置,然后use lib加载它。

# use lib /a special directory/
BEGIN {
    my $lib_to_include = ...;

    require lib;
    lib->import($lib_to_include);
}

use Module_That_Requires_Special_Dir;

唯一需要注意的是,无论用于加载自定义包含目录的代码,都必须依赖于此BEGIN块之前已定义的方法。因此,您无法使用稍后在文件中的子例程。

答案 2 :(得分:0)

遇到only,似乎让路径传递给use参数,如下所示:

use only { versionlib => '/home/ingy/modules' },
        MyModule => 0.33;

它必须与版本条件一起使用,但无论如何都要放在这里,因为它与我的问题1相关,我无法在第一时间找到任何模块,允许在@外面的路径INC。

根据{{​​3}}和

require据说能够完整的路径

require "$ENV{HOME}/lib/Foo.pm"; # no @INC searching!