Perl的@INC是如何构build的? (又名什么是影响Perl模块search的方法?

影响Perl模块search的所有方法是什么? 或者, Perl的@INC是如何构build的

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

在StackOverflow中似乎没有全面的“@INC”常见问题解答types的post,所以这个问题是作为一个。

我们将看看这个数组的内容是如何构造的,并且可以被操纵来影响Perl解释器将在哪里find模块文件。

  1. 默认@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

  2. 环境variablesPERL5LIB (或PERLLIB

    Perl预先将@INC与包含在你的shell的PERL5LIB (如果没有定义,使用PERLLIB )环境variables中的目录列表(以冒号分隔)相关PERL5LIB 。 在PERL5LIBPERLLIB环境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 . 
  3. -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章)

  4. 通过lib杂注传递它

    Perl预先将@INC与通过use lib传递给它的目录列表@INC

    在一个程序中:

     use lib ("/dir1", "/dir2"); 

    在命令行上:

     perl -Mlib=/dir1,/dir2 

    你也可以通过no lib@INC删除目录 。

  5. 你可以直接操作@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还有两种方法:

  1. /Library/Perl/x.xx/AppendToPath文件。 此文件中列出的path在运行时会附加到@INC。

  2. /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导出。