七度&光 2010-03-26 21:14 采纳率: 22.2%
浏览 485
已采纳

的@inc 是如何构建的? (又名: 所有影响 Perl 模块搜索位置的方法是什么?)

What are all the ways of affecting where Perl modules are searched for? or, How is Perl's @INC constructed?

As we know, Perl uses @INC array containing directory names to determine where to search for Perl module files.

There does not seem to be a comprehensive "@INC" FAQ-type post on StackOverflow, so this question is intended as one.

转载于:https://stackoverflow.com/questions/2526804/how-is-perls-inc-constructed-aka-what-are-all-the-ways-of-affecting-where-pe

  • 写回答

3条回答

  • 七度&光 2010-03-26 21:15
    关注

    We will look at how the contents of this array are constructed and can be manipulated to affect where the Perl interpreter will find the module files.

    1. Default @INC

      Perl interpreter is compiled with a specific @INC default value. To find out this value, run env -i perl -V command (env -i ignores the PERL5LIB environmental variable - see #2) and in the output you will see something like this:

      $ 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
       .
      

    Note . at the end; this is the current directory (which is not necessarily the same as the script's directory). It is missing in Perl 5.26+, and when Perl runs with -T (taint checks enabled).

    To change the default path when configuring Perl binary compilation, set the configuration option otherlibdirs:

    Configure -Dotherlibdirs=/usr/lib/perl5/site_perl/5.16.3

    1. 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
       .
      
    2. -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)

    3. 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.

    4. 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.

    Note: The directories are unshifted onto @INC in the order listed in this answer, e.g. default @INC is last in the list, preceded by PERL5LIB, preceded by -I, preceded by use lib and direct @INC manipulation, the latter two mixed in whichever order they are in Perl code.

    References:

    There does not seem to be a comprehensive @INC FAQ-type post on Stack Overflow, so this question is intended as one.

    When to use each approach?

    • 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?).

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 求差集那个函数有问题,有无佬可以解决
  • ¥15 【提问】基于Invest的水源涵养
  • ¥20 微信网友居然可以通过vx号找到我绑的手机号
  • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
  • ¥15 解riccati方程组
  • ¥15 display:none;样式在嵌套结构中的已设置了display样式的元素上不起作用?
  • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
  • ¥50 树莓派安卓APK系统签名
  • ¥65 汇编语言除法溢出问题