影响Perl模块搜索位置的所有方法是什么? 或者,Perl的@INC是如何构造的?

我们知道,Perl使用包含目录名的@INC数组来确定在哪里搜索Perl模块文件。

在StackOverflow上似乎没有一个全面的“@INC”常见问题类型的帖子,所以这个问题是一个。


我们将看看这个数组的内容是如何构造的,以及如何操作它来影响Perl解释器在哪里找到模块文件。

默认@INC Perl解释器是用特定的@INC默认值编译的。要找到这个值,运行env -i perl - v命令(env -i忽略PERL5LIB环境变量-参见#2),在输出中你会看到如下内容: $ env -i perl -V ... @INC: /usr/lib/perl5/site_perl/5.18.0/x86_64-linux-thread-multi-ld /usr/lib/perl5/site_perl/5.18.0 /usr/lib/perl5/5.18.0/x86_64-linux-thread-multi-ld /usr/lib/perl5/5.18.0 .

请注意。最后;这是当前目录(不一定与脚本的目录相同)。在Perl 5.26+中,以及在Perl运行-T(启用了污点检查)时,它都没有。

要在配置Perl二进制编译时更改默认路径,请设置配置选项otherlibdirs:

配置-Dotherlibdirs = / usr / lib / perl5 / site_perl / 5.16.3

Environmental variable PERL5LIB (or PERLLIB) Perl pre-pends @INC with a list of directories (colon-separated) contained in PERL5LIB (if it is not defined, PERLLIB is used) environment variable of your shell. To see the contents of @INC after PERL5LIB and PERLLIB environment variables have taken effect, run perl -V. $ perl -V ... %ENV: PERL5LIB="/home/myuser/test" @INC: /home/myuser/test /usr/lib/perl5/site_perl/5.18.0/x86_64-linux-thread-multi-ld /usr/lib/perl5/site_perl/5.18.0 /usr/lib/perl5/5.18.0/x86_64-linux-thread-multi-ld /usr/lib/perl5/5.18.0 . -I command-line option Perl pre-pends @INC with a list of directories (colon-separated) passed as value of the -I command-line option. This can be done in three ways, as usual with Perl options: Pass it on command line: perl -I /my/moduledir your_script.pl Pass it via the first line (shebang) of your Perl script: #!/usr/local/bin/perl -w -I /my/moduledir Pass it as part of PERL5OPT (or PERLOPT) environment variable (see chapter 19.02 in Programming Perl) Pass it via the lib pragma Perl pre-pends @INC with a list of directories passed in to it via use lib. In a program: use lib ("/dir1", "/dir2"); On the command line: perl -Mlib=/dir1,/dir2 You can also remove the directories from @INC via no lib. You can directly manipulate @INC as a regular Perl array. Note: Since @INC is used during the compilation phase, this must be done inside of a BEGIN {} block, which precedes the use MyModule statement. Add directories to the beginning via unshift @INC, $dir. Add directories to the end via push @INC, $dir. Do anything else you can do with a Perl array.

注意:目录没有按照答案中列出的顺序转移到@INC上,例如默认的@INC在列表的最后,前面是PERL5LIB,前面是-I,前面是use lib和直接@INC操作,后两者按照它们在Perl代码中的顺序混合。

引用:

perldoc perlmod perldoc自由 Perl模块机制——一个包含实用HOW-TOs的伟大指南 我如何“使用”一个Perl模块在一个目录不是在@INC? Perl编程-第31章第13部分,章节7.2.41 Perl程序如何知道在哪里找到包含它使用的Perl模块的文件?

在Stack Overflow上似乎没有一个全面的@INC常见问题类型的帖子,所以这个问题是一个。

何时使用每种方法?

If the modules in a directory need to be used by many/all scripts on your site, especially run by multiple users, that directory should be included in the default @INC compiled into the Perl binary. If the modules in the directory will be used exclusively by a specific user for all the scripts that user runs (or if recompiling Perl is not an option to change default @INC in previous use case), set the users' PERL5LIB, usually during user login. Note: Please be aware of the usual Unix environment variable pitfalls - e.g. in certain cases running the scripts as a particular user does not guarantee running them with that user's environment set up, e.g. via su. If the modules in the directory need to be used only in specific circumstances (e.g. when the script(s) is executed in development/debug mode, you can either set PERL5LIB manually, or pass the -I option to perl. If the modules need to be used only for specific scripts, by all users using them, use use lib/no lib pragmas in the program itself. It also should be used when the directory to be searched needs to be dynamically determined during runtime - e.g. from the script's command line parameters or script's path (see the FindBin module for very nice use case). If the directories in @INC need to be manipulated according to some complicated logic, either impossible to too unwieldy to implement by combination of use lib/no lib pragmas, then use direct @INC manipulation inside BEGIN {} block or inside a special purpose library designated for @INC manipulation, which must be used by your script(s) before any other modules are used. An example of this is automatically switching between libraries in prod/uat/dev directories, with waterfall library pickup in prod if it's missing from dev and/or UAT (the last condition makes the standard "use lib + FindBin" solution fairly complicated. A detailed illustration of this scenario is in How do I use beta Perl modules from beta Perl scripts?. An additional use case for directly manipulating @INC is to be able to add subroutine references or object references (yes, Virginia, @INC can contain custom Perl code and not just directory names, as explained in When is a subroutine reference in @INC called?).


除了上面列出的位置之外,OS X版本的Perl还有两种方法:

/图书馆/ Perl / x。xx / AppendToPath文件。该文件中列出的路径在运行时被追加到@INC。 /图书馆/ Perl / x。xx / PrependToPath文件。该文件中列出的路径在运行时被加在@INC前面。


正如前面所说,@INC是一个数组,您可以随意添加任何内容。

我的CGI REST脚本看起来像这样:

#!/usr/bin/perl
use strict;
use warnings;
BEGIN {
    push @INC, 'fully_qualified_path_to_module_wiht_our_REST.pm';
}
use Modules::Rest;
gone(@_);

Rest.pm导出子例程gone。