perl:仅为当前范围更改@INC

perl: change @INC for current scope only

对 Perl 的 @INC 数组的修改对于单个范围来说似乎非常混乱。我想澄清一下,因为它似乎在与任何动态初始化对象的方法作斗争。

有人认为我可以将其定义为本地来解决这个问题。

根据手册,"local modifies the listed variables to be local to the enclosing block, file, or eval."

让我烦恼的部分是 "or" 部分。

问题:我想更改 @INC 数组以在某些情况下仅包含一个目录,并且仅针对当前文件。

示例尝试和问题:

假设我有一个启动脚本 index.pl:

#!/usr/bin/perl
use strict;
use warnings FATAL => 'all';

use File::Basename;
# Lets say I want to modify @INC here to look in ONLY one path.  Local
# should allow us to declare for one scope or file (how non explicit this
# is annoys me) Since I have not defined a scope with brackets, it should
# be effective for the current file

local @INC = (dirname(__FILE__) . '/foo/'); #some relative path

# Lets say bar now uses standard perl modules
require 'bar.pm';
# ^- This will fail because local did not work as described, fails at use
# XML::Simple because it is traversing foo

my $bar = bar->new();

为了全面起见,这里贴一个bar.pm:

package bar;
use strict;
use warnings;

sub new
{
    my $class = shift;
    my $self = bless {}, $class;

    use XML::Simple;
    return $self;
}
1;

是否可以仅针对当前文件修改@INC,同时在之后的所有已解析文件中保持不变?

(我知道我可以取消移位,但最终可能会遍历几十个目录)

require(dirname(__FILE__) . '/foo/bar.pm');

local @INC 有效,但是您的 bar.pm 文件仍然需要能够找到 XML/Simple.pm(在编译文件时执行 use 语句,无论它出现在文件中的什么位置),大概来自原始 @INC,因此您的本地 @INC 应该从原始 @INC.

的副本开始
{
    local @INC = (dirname(__FILE__) . '/foo/', @INC);

    require 'bar.pm';
}        # local @INC out of scope now, original @INC restored

my $bar = bar->new();
use File::Basename;
use subs 'require';
sub require {
    my $module_file = shift;
    die "unexpected absolute path $module_file\n" if $module_file =~ /^\//;
    CORE::require(dirname(__FILE__) . '/foo/' . $module_file);
}

http://perldoc.perl.org/CORE.html#OVERRIDING-CORE-FUNCTIONS