Perl的@INC是如何构build的? (又名什么是影响Perl模块search的方法?
影响Perl模块search的所有方法是什么? 或者, Perl的@INC是如何构build的 ?
我们知道, Perl使用包含目录名的@INC
数组来确定在哪里searchPerl模块文件 。
在StackOverflow中似乎没有全面的“@INC”常见问题解答types的post,所以这个问题是作为一个。
我们将看看这个数组的内容是如何构造的,并且可以被操纵来影响Perl解释器将在哪里find模块文件。
-
默认
@INC
Perl解释器是用特定的
@INC
默认值编译的 。 要找出这个值,运行env -i perl -V
命令(env -i
忽略PERL5LIB
环境variables – 见#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运行时使用-T
(启用了污点检查)时缺失。要在configurationPerl二进制编译时更改默认path,请设置configuration选项
otherlibdirs
:Configure -Dotherlibdirs=/usr/lib/perl5/site_perl/5.16.3
-
环境variables
PERL5LIB
(或PERLLIB
)Perl预先将
@INC
与包含在你的shell的PERL5LIB
(如果没有定义,使用PERLLIB
)环境variables中的目录列表(以冒号分隔)相关PERL5LIB
。 在PERL5LIB
和PERLLIB
环境variables已经生效后,要查看@INC
的内容,请运行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
命令行选项Perl预先将
@INC
与作为-I
命令行选项的值传递的目录列表(以冒号分隔)进行传递。 这可以通过三种方式完成,像往常一样使用Perl选项:-
通过命令行传递:
perl -I /my/moduledir your_script.pl
-
通过Perl脚本的第一行(shebang)传递它:
#!/usr/local/bin/perl -w -I /my/moduledir
-
将它作为
PERL5OPT
(或PERLOPT
)环境variables的一部分传递(请参见Perl编程中的第19.02章)
-
-
通过
lib
杂注传递它Perl预先将
@INC
与通过use lib
传递给它的目录列表@INC
。在一个程序中:
use lib ("/dir1", "/dir2");
在命令行上:
perl -Mlib=/dir1,/dir2
你也可以通过
no lib
从@INC
删除目录 。 -
你可以直接操作
@INC
作为普通的Perl数组。注意:由于在编译阶段使用
@INC
,因此必须在use MyModule
语句之前的BEGIN {}
块中完成。-
通过
unshift @INC, $dir
添加目录到开头。 -
通过
push @INC, $dir
将目录添加到最后。 -
做任何你可以用Perl数组做的事情。
-
注意:这个目录是按照这个答案列出的顺序在@INC
上移动的 ,例如默认@INC
是列表中的最后一个,前面是PERL5LIB
,前面是-I
,前面是use lib
和直接@INC
操作,后面两个混合无论他们在Perl代码中的顺序。
参考文献:
- perldoc perlmod
- perldoc lib
- Perl模块机制 – 一个包含实用HOW-TO的伟大指南
- 如何在不在
@INC
的目录中使用Perl模块? - 编程Perl – 第31章第13部分,通道7.2.41
- Perl程序如何知道在哪里可以find包含Perl模块的文件?
Stack Overflow似乎没有一个全面的@INC
FAQtypes的post,所以这个问题只能作为一个。
何时使用每种方法?
-
如果目录中的模块需要被站点上的许多/所有脚本使用,特别是由多个用户运行,那么该目录应该包含在编译到Perl二进制文件中的默认
@INC
。 -
如果目录中的模块将被特定的用户专门用于所有用户运行的脚本(或者在以前的用例中,重新编译Perl不是更改默认
@INC
的选项),请设置用户的PERL5LIB
,通常在用户login。注意:请注意通常的Unix环境variables缺陷 – 例如在某些情况下运行脚本,因为特定的用户不能保证在设置了用户环境的情况下运行它们,例如通过
su
。 -
如果目录中的模块只能在特定情况下使用(例如在开发/debugging模式下执行脚本),则可以手动设置
PERL5LIB
,或将-I
选项传递给perl。 -
如果模块仅用于特定脚本, 所有使用它们的用户都可以在程序中
use lib
/no lib
pragmas。 当运行时需要dynamic确定要search的目录时(例如,从脚本的命令行参数或脚本path(请参阅FindBin模块以获得非常好的用例)),也应该使用它。 -
如果
@INC
的目录需要根据一些复杂的逻辑进行操作,要么通过use lib
/no lib
编译指令的组合来实现是不可能的,要么在BEGIN {}
块中使用直接的@INC
操作,要么在专用库指定用于@INC
操作,在使用任何其他模块之前,脚本必须使用它们。一个例子就是在prod / uat / dev目录下的库之间自动切换,如果在dev和/或UAT中没有find瀑布库,最后的条件使得标准的“使用lib + FindBin”解决scheme变得相当复杂。这个场景的详细说明是如何使用Beta Perl脚本中的beta Perl模块?
-
直接操作
@INC
的另一个用例是能够添加子程序引用或对象引用(是的,Virginia,@INC
可以包含自定义的Perl代码,而不仅仅是目录名,正如@INC中的子例程引用? )。
除了上面列出的位置之外,OS X版本的Perl还有两种方法:
-
/Library/Perl/x.xx/AppendToPath文件。 此文件中列出的path在运行时会附加到@INC。
-
/Library/Perl/x.xx/PrependToPath文件。 在这个文件中列出的path在运行时被添加到@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导出。