我想在BEGINPerl脚本的块中使用外部库.我做的第一个测试是检查@INC如果我推出一些值,我是否会变成人物:
use strict;
use warnings;
BEGIN {
push @INC, "d:/external_pm/";
use Data::Dumper;
print Dumper @INC;
}
Run Code Online (Sandbox Code Playgroud)
哪个按预期工作并显示:
$VAR1 = 'D:/perl/5163/site/lib';
$VAR2 = 'D:/perl/5163/lib';
$VAR3 = '.'; # I am not sure about this one?!
$VAR4 = 'd:/external_pm/';
Run Code Online (Sandbox Code Playgroud)
现在我想在以下后面导入一个模块push:
use strict;
use warnings;
BEGIN {
push @INC, "d:/external_pm/";
use Data::Dumper;
print Dumper @INC;
use ExtScript;
}
Run Code Online (Sandbox Code Playgroud)
接下来的错误显示我@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的一个失误?
use语句在编译时执行(特别是在BEGIN阶段),而普通代码稍后运行.我们来看看这个简化的片段:
BEGIN {
push @INC, "some/dir";
use Example;
}
Run Code Online (Sandbox Code Playgroud)
如果我们明确说明所有阶段,那将相当于:
BEGIN {
push @INC, "some/dir";
BEGIN { require Example; Example->import() }
}
Run Code Online (Sandbox Code Playgroud)
因此,Example模块将在push运行之前导入.
有很多方法可以解决这个问题.
最简单的方法是只将@INC操作放入BEGIN块,然后将模块导入到外部:
BEGIN { push @INC, "some/dir" }
use Example;
Run Code Online (Sandbox Code Playgroud)
更好的解决方案是使用libpragma来处理@INC:
use lib "some/dir";
use Example;
Run Code Online (Sandbox Code Playgroud)
但是,存在一个主要区别:use lib在模块搜索路径的开头放置其他目录,因此您可能会意外地覆盖其他模块.push @INC只会在最后添加目录,如果在其他位置找不到模块则作为后备.
| 归档时间: |
|
| 查看次数: |
316 次 |
| 最近记录: |