背景:我有一个 perl 模块——我们称它为 Foo::Common
,它已安装在我们的一个文件服务器上(为了简单起见,我将其称为“全局” ' 版本)。该模块包含在每 15 分钟启动一次的大约 1000 个 perl 脚本的某个位置。该模块有几个旧版本,但更新它需要在几个月的时间里进行大量测试。
我正在编写一个将在同一处理服务器上运行的新 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
有隐式 BEGIN
语句。
我该如何处理?
最佳答案
太阳底下并无新鲜事。
use <a href="http://search.cpan.org/perldoc?only%3a%3alatest" rel="noreferrer noopener nofollow">only::latest</a> 'Foo::Common'
关于perl - 如何根据模块版本有条件地更改@INC?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12714032/