我想在Perl脚本的BEGIN
块中使用外部库。
我做的第一个测试是检查我的@INC
是否会因为推送一些值而被人员插入:
use strict;
use warnings;
BEGIN {
push @INC, "d:/external_pm/";
use Data::Dumper;
print Dumper @INC;
}
哪个按预期工作并显示:
$VAR1 = 'D:/perl/5163/site/lib';
$VAR2 = 'D:/perl/5163/lib';
$VAR3 = '.'; # I am not sure about this one?!
$VAR4 = 'd:/external_pm/';
现在我想在push
:
use strict;
use warnings;
BEGIN {
push @INC, "d:/external_pm/";
use Data::Dumper;
print Dumper @INC;
use ExtScript;
}
以下错误告诉我@INC
未更新:
Can't locate ExtScript.pm in @INC (@INC contains: D:/perl/5163/site/lib
D:/perl/5163/lib .) at file.pl line 9.
BEGIN failed--compilation aborted at file.pl line 9.
为什么@INC
没有更新?
我无法导入BEGIN
块中的模块?或者是Perl的用途?
答案 0 :(得分:9)
use
语句在编译时执行(特别是在BEGIN阶段),而普通代码稍后运行。让我们看一下这个简化的片段:
BEGIN {
push @INC, "some/dir";
use Example;
}
如果我们明确说明所有阶段,那将等同于:
BEGIN {
push @INC, "some/dir";
BEGIN { require Example; Example->import() }
}
因此Example
模块将在push
运行之前导入。
有很多方法可以解决这个问题。
最简单的方法是将仅 @INC
操作放入BEGIN块,然后将模块导入外部:
BEGIN { push @INC, "some/dir" }
use Example;
更好的解决方案是使用lib
pragma来处理@INC
:
use lib "some/dir";
use Example;
但是,存在一个主要区别:use lib
会在模块搜索路径的开头放置其他目录,因此您可能会意外覆盖其他模块。 push @INC
只会在最后添加目录,如果在其他位置找不到模块,则会作为后备。
答案 1 :(得分:3)
use ExtScript;
在push @INC
之前执行。任
use ExtScript;
移出BEGIN
区块require
/ import
-I
命令行选项或PERL5LIB
env变量。