【发布时间】:2012-10-04 02:54:45
【问题描述】:
背景:我有一个 perl 模块——我们称之为Foo::Common,它已安装在我们的一个文件服务器上(为简单起见,我将其称为“全局”版本)。该模块包含在大约 1000 个 perl 脚本中,每 15 分钟启动一次。该模块有几个版本,但更新它需要几个月的时间进行大量测试。
我正在编写一个新的 perl 脚本,它将在同一处理服务器上运行,但我需要仅包含在最新版本的 Foo::Common 中的功能。如果我只是想使用较新版本的Foo::Common,我可以将Foo/Common.pm 放在运行脚本的./lib目录中,然后使用以下代码:
my $lib = '';
BEGIN {
$lib = $ENV{FOO_ENV_HOME} || '';
}
use lib "$lib/core/bin/";
use lib './lib';
use Foo::Common;
因为use lib将目录添加到@INC的开头,所以会先找到并使用较新版本的Foo::Common。
这一切都很好,但我不希望我的脚本依赖于 Foo::Common 的本地版本。 Foo::Common的全球版有our $VERSION = '1.1.2',我想本地安装的版本是1.1.7。如果我部署上面的代码,然后我们将全局版本升级到尚未编写的1.2.0,我的脚本将卡在运行1.1.7。
根据perldoc -f require:
`require $filename` Has semantics similar to the following subroutine:
sub require {
my ($filename) = @_;
if (exists $INC{$filename}) {
return 1 if $INC{$filename};
die "Compilation failed in require";
}
my ($realfilename,$result);
ITER: {
foreach $prefix (@INC) {
$realfilename = "$prefix/$filename";
if (-f $realfilename) {
$INC{$filename} = $realfilename;
$result = do $realfilename;
last ITER;
}
}
die "Can't find $filename in \@INC";
}
if ($@) {
$INC{$filename} = undef;
die $@;
} elsif (!$result) {
delete $INC{$filename};
die "$filename did not return true value";
} else {
return $result;
}
}
我不清楚这如何与use MODULE VERSION 语法交互,尽管What does Perl do when two versions of a module are installed? 的答案中的讨论表明use Module Version 是不够的。
我假设我要操作@INC,但我不确定如何根据每个模块的$VERSION 来操作,尤其是因为use 有一个隐含的BEGINstatement。
我该如何处理?
【问题讨论】: