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

und*_*ble 2 perl perl-module

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

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

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

amo*_*mon 8

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

BEGIN {
    print "This is executed as soon as the block has been parsed\n";
}
Run Code Online (Sandbox Code Playgroud)

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

例如,use语句对于BEGIN块来说实际上是语法糖.

use Foo::Bar qw/baz qux/;
Run Code Online (Sandbox Code Playgroud)

相当于

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

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

所以我们有三个选择:

  1. BEGIN阶段中加载配置并在加载实际模块之前添加正确的库路径
  2. BEGIN完整路径期间手动加载模块(例如,require "/my/modules/Foo/Bar.pm"
  3. 在运行时计算出配置,然后加载模块.

使用裸require是相当不舒服的,这就是为什么Module::Runtime存在