有什么方法可以影响在哪里搜索Perl模块?或者,如何构造Perl的@INC?
众所周知,Perl使用@INC
包含目录名称的数组来确定在何处搜索Perl模块文件。
在StackOverflow上似乎没有完整的“ @INC”常见问题解答类型的文章,因此此问题仅供参考。
@INC
运行时如何添加,而不是完整的构造。
有什么方法可以影响在哪里搜索Perl模块?或者,如何构造Perl的@INC?
众所周知,Perl使用@INC
包含目录名称的数组来确定在何处搜索Perl模块文件。
在StackOverflow上似乎没有完整的“ @INC”常见问题解答类型的文章,因此此问题仅供参考。
@INC
运行时如何添加,而不是完整的构造。
Answers:
我们将研究如何构造此数组的内容,以及如何操纵该数组的内容以影响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
:
Configure -Dotherlibdirs=/usr/lib/perl5/site_perl/5.16.3
环境变量PERL5LIB
(或PERLLIB
)
Perl @INC
附带了外壳程序环境变量PERL5LIB
(如果未定义,PERLLIB
则使用)中包含的目录列表(以冒号分隔)。要查看@INC
after PERL5LIB
和PERLLIB
环境变量生效的内容,请运行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
)环境变量的一部分传递(请参阅《Perl编程》中的第19.02章)。
Perl预先@INC
添加了通过传递给它的目录列表use lib
。
在程序中:
use lib ("/dir1", "/dir2");
在命令行上:
perl -Mlib=/dir1,/dir2
您也可以从除去目录@INC
通过no lib
。
您可以直接将其@INC
作为常规Perl数组进行操作。
注意:由于@INC
是在编译阶段使用的,因此必须BEGIN {}
在use MyModule
语句之前的块内完成。
通过将目录添加到开头unshift @INC, $dir
。
通过将目录添加到末尾push @INC, $dir
。
做您可以使用Perl数组做的其他事情。
注:该目录未移动到@INC
在这个回答中列出的顺序,比如默认@INC
是在列表的最后,通过前面PERL5LIB
,前面加-I
,前面有use lib
直接@INC
操纵,后两者混在哪个顺序排列在Perl代码。
@INC
?似乎@INC
在Stack Overflow上没有完整的FAQ类型帖子,因此此问题仅供参考。
如果目录中的模块需要由站点上的许多/所有脚本使用,尤其是由多个用户运行,则该目录应包含在默认@INC
编译为Perl二进制文件中的目录中。
如果目录中的模块将由特定用户专用于该用户运行的所有脚本(或者如果重新编译Perl不能@INC
在以前的用例中更改默认值),则PERL5LIB
通常在用户登录期间设置用户的。
注意:请注意通常的Unix环境变量陷阱-例如,在某些情况下,以特定用户的身份运行脚本并不能保证在该用户的环境设置下运行脚本(例如通过)su
。
如果目录中的模块仅在特定情况下需要使用(例如,在开发/调试模式下执行脚本时),则可以PERL5LIB
手动设置或将-I
选项传递给perl。
如果模块仅需要用于特定脚本,则所有使用它们的用户都应在程序本身中使用use lib
/ no lib
pragmas。当需要在运行时动态确定要搜索的目录时,也应使用它(例如,从脚本的命令行参数或脚本的路径来确定)(有关非常好的用例,请参见FindBin模块)。
如果@INC
需要根据某些复杂的逻辑来操作目录,或者无法通过use lib
/ no lib
pragma 的组合来实现,那么请@INC
在BEGIN {}
块内部或指定用于@INC
操作的专用库中使用直接操作,这些脚本必须由脚本使用(s),然后再使用其他任何模块。
一个示例是自动在prod / uat / dev目录中的库之间切换,如果在dev和/或UAT中缺少瀑布库拾取,则在prod中使用瀑布库拾取(最后一个条件使标准的“ use lib + FindBin”解决方案相当复杂。如何使用Beta Perl脚本中的beta Perl模块?中对此场景的详细说明。
直接操作的另一个用例@INC
是能够添加子例程引用或对象引用(是的,弗吉尼亚州,@INC
可以包含自定义Perl代码,而不仅仅是目录名称,如@INC中的子例程引用何时被调用?中所述)。