或者,Perl的@INC是如何构建的?
我们知道,Perl uses @INC
array containing directory names to determine where to search for Perl module files。
在StackOverflow上似乎没有一个全面的“@INC”常见问题类型的帖子,所以这个问题是一个意思。
解决方法
>默认@INC
Perl解释器是compiled with a specific @INC
default value.要找出这个值,请运行env -i perl -V命令(env -i忽略PERL5LIB环境变量 – 参见#2),并在输出中将看到如下所示:
06000
注意 。最后;这是当前目录。当Perl与-T
(taint checks enabled)一起运行时,它缺失。
要在配置Perl二进制编译时更改默认路径,请设置配置选项otherlibdirs
:
Configure -Dotherlibdirs=/usr/lib/perl5/site_perl/5.16.3
>环境变量PERL5LIB(或PERLLIB)
Perl预先在@INC上提供了包含在shell的环境变量的PERL5LIB(如果未定义,使用PERLLIB)中的目录(冒号分隔)的列表。要在PERL5LIB和PERLLIB环境变量生效后查看@INC的内容,请运行perl -V。
06001
> -I命令行选项
Perl预先将@INC与作为-I命令行选项的值传递的目录列表(冒号分隔)。这可以通过三种方式完成,像Perl选项一样:
>在命令行传递:
perl -I /my/moduledir your_script.pl
>通过Perl脚本的第一行(shebang)传递:
#!/usr/local/bin/perl -w -I /my/moduledir
>将其作为PERL5OPT(或PERLOPT)环境变量的一部分传递(参见Programming Perl中的章节19.02)
>通过lib
pragma传递
Perl预先将@INC与通过使用lib传递到它的目录列表。
在程序中:
use lib ("/dir1","/dir2");
在命令行上:
perl -Mlib=/dir1,/dir2
你也可以remove the directories from @INC
via no lib
。
>你可以直接操作@INC作为一个普通的Perl数组。
注:由于在编译阶段使用了@INC,因此必须在使用MyModule语句之前的BEGIN {}块中完成。
>通过unshift @INC,$ dir将目录添加到开头。
>通过push @INC,$ dir将目录添加到末尾。
>做一些你可以用Perl数组做的事情。
注意:目录不会按照此答案中列出的顺序移到@INC上。默认@INC是列表中的最后一个,前面是PERL5LIB,前面是-I,前面是使用lib和直接的@INC操作,后两个以Perl代码的顺序混合。
参考文献:
> perldoc perlmod
> perldoc lib
> Perl Module Mechanics – a great guide containing practical HOW-TOs
> How do I ‘use’ a Perl module in a directory not in @INC
?
> Programming Perl – 第31章第13部分,第7.2.41节
> How does a Perl program know where to find the file containing Perl module it uses?
在Stack Overflow上似乎没有一个全面的@INC FAQ类型的文章,所以这个问题是一个意思。
什么时候使用每种方法?
>如果一个目录中的模块需要被您站点上的许多/所有脚本使用,特别是由多个用户运行,那么该目录应该包含在编译成Perl二进制文件的默认@INC中。
>如果目录中的模块将由特定用户专用于用户运行的所有脚本(或者如果重新编译Perl不是在先前使用情况下更改默认@INC的选项),请设置用户的PERL5LIB,通常在用户登录。
注意:请注意通常的Unix环境变量陷阱 – 例如。在某些情况下,作为特定用户运行脚本不能保证在设置的用户环境中运行它们。通过su。
>如果目录中的模块仅在特定情况下使用(例如,当脚本在开发/调试模式下执行时,您可以手动设置PERL5LIB,也可以将-I选项传递给perl。
>如果模块只需要使用特定的脚本,所有用户使用它们,请在程序中使用lib / no lib pragmas。当需要在运行时动态确定要搜索的目录时,也应当使用它。从脚本的命令行参数或脚本的路径(参见FindBin模块非常漂亮的用例)。
>如果@INC中的目录需要根据一些复杂的逻辑操作,或者不可能太难以通过使用lib / no lib pragmas的组合来实现,那么在BEGIN {}块内部或在特殊目的内部使用直接的@INC操作指定为@INC操作的库,在使用任何其他模块之前,必须由您的脚本使用。
一个示例是在prod / uat / dev目录中的库之间自动切换,如果dev和/或UAT中缺少瀑布库,则会在prod中检索瀑布库(最后一个条件使标准的“use lib FindBin”解决方案相当复杂。
这种情况的详细说明在How do I use beta Perl modules from beta Perl scripts?。
>直接操作@INC的附加用例是能够添加子例程引用或对象引用(是,Virginia,@INC可以包含自定义Perl代码,而不仅仅是目录名称,如When is a subroutine reference in @INC called?中所述)。