2

背景:我有一个 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::Commonour $VERSION = '1.1.2',我要本地安装的版本是1.1.7。如果我部署上面的代码,然后我们将全局版本升级到尚未编写的1.2.0,我的脚本会卡在 running 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语法交互,尽管在安装两个版本的模块时 Perl 会做什么的答案中进行了讨论?表示use Module Version还不够。

我假设我要操作@INC,但我不确定如何根据每个模块的来执行此操作$VERSION,特别是因为use有一个隐式BEGIN声明。

我该如何处理?

4

2 回答 2

4

太阳底下没有新鲜事。

use only::latest 'Foo::Common'

于 2012-10-03T18:54:45.150 回答
2

您无法根据版本进行检查,因为$VERSION直到它被加载(也就是执行)之后才存在。


所以你想要使用“全局”版本(如果存在),否则使用本地版本?将本地路径附加到 @INC 而不是预先添加它。

BEGIN {
   push @INC, "$ENV{FOO_ENV_HOME}/core/bin";
      if $ENV{FOO_ENV_HOME};
}

use Foo::Common;

@INC如果您因为会影响其他内容而无法重新排列,请尝试在更改之前加载 Foo::Common @INC

BEGIN { eval { require Foo::Common; }; }
use lib ...;
use Foo::Common;
use ...;

如果之前已经加载过,则不会加载该use Foo::Common;模块,并且它将从已加载的任何版本导入(无论它在何处加载)。

于 2012-10-03T17:55:34.777 回答