Perl的@INC是如何构造的? (又有什么方法可以影响搜索Perl模块的位置?) [英] How is Perl's @INC constructed? (aka What are all the ways of affecting where Perl modules are searched for?)
问题描述
有什么方法可以影响搜索Perl模块的位置? 或者, Perl的@INC是如何构建的?
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.
在StackOverflow上似乎没有完整的"@INC"常见问题解答类型的文章,因此,本问题仅供参考.
There does not seem to be a comprehensive "@INC" FAQ-type post on StackOverflow, so this question is intended as one.
推荐答案
我们将研究如何构造此数组的内容,并对其进行操作以影响Perl解释器在哪里找到模块文件.
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.
-
默认
@INC
Perl解释器是编译的,具有特定的@INC
默认值.要找出该值,请运行env -i perl -V
命令(env -i
忽略PERL5LIB
环境变量-参见#2),然后在输出中将看到类似以下内容的内容:
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
.
最后请注意.
;这是当前目录(不必与脚本目录相同).在Perl 5.26及更高版本中以及Perl与 -T
一起运行时,缺少该属性(启用了污点检查).
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).
要在配置Perl二进制编译时更改默认路径,请设置配置选项 otherlibdirs
:
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
-
环境变量
PERL5LIB
(或PERLLIB
)
Perl在@INC
前面加上外壳的PERL5LIB
(如果未定义,则使用PERLLIB
)中包含的目录列表(以冒号分隔).要在PERL5LIB
和PERLLIB
环境变量生效后查看@INC
的内容,请运行perl -V
.
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
.
-I
命令行选项
-I
command-line option
Perl用-I
命令行选项的值传递的目录列表(用冒号分隔)预先附加在@INC
之前.与Perl选项一样,可以通过三种方式完成此操作:
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
通过Perl脚本的第一行(shebang)传递它:
Pass it via the first line (shebang) of your Perl script:
#!/usr/local/bin/perl -w -I /my/moduledir
将其作为PERL5OPT
(或PERLOPT
)环境变量的一部分传递(请参见编程Perl )
Pass it as part of PERL5OPT
(or PERLOPT
) environment variable (see chapter 19.02 in Programming Perl)
通过 lib
编译指示
Pass it via the lib
pragma
Perl在@INC
前面加上了通过use lib
传入的目录列表.
Perl pre-pends @INC
with a list of directories passed in to it via use lib
.
在程序中:
use lib ("/dir1", "/dir2");
在命令行上:
perl -Mlib=/dir1,/dir2
您还可以通过
You can also remove the directories from @INC
via no lib
.
您可以直接将@INC
作为常规Perl数组进行操作.
You can directly manipulate @INC
as a regular Perl array.
注意:由于在编译阶段使用了@INC
,因此必须在use MyModule
语句之前的BEGIN {}
块内部完成.
Note: Since @INC
is used during the compilation phase, this must be done inside of a BEGIN {}
block, which precedes the use MyModule
statement.
-
通过
unshift @INC, $dir
将目录添加到开头.
通过push @INC, $dir
将目录添加到末尾.
Add directories to the end via push @INC, $dir
.
使用Perl数组可以做其他任何事情.
Do anything else you can do with a Perl array.
注意:目录按此答案中列出的顺序未移位到@INC
上,例如默认的@INC
在列表的最后,在PERL5LIB
之后,在-I
之后,在use lib
和直接@INC
操作之前,后两者以Perl代码中的顺序混合.
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.
- perldoc perlmod
- perldoc库
- Perl模块力学-包含实用HOW-TO的出色指南
- 如何在
@INC
以外的目录中使用" Perl模块? - 编程Perl -第31章,第13部分ch 7.2.41
- 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 - chapter 31 part 13, ch 7.2.41
- How does a Perl program know where to find the file containing Perl module it uses?
关于Stack Overflow似乎没有一个全面的@INC
常见问题解答类型的帖子,因此该问题仅供参考.
There does not seem to be a comprehensive @INC
FAQ-type post on Stack Overflow, so this question is intended as one.
-
如果目录中的模块需要由站点上的许多脚本/所有脚本使用,尤其是由多个用户运行,则该目录应包含在编译为Perl二进制文件的默认
@INC
中.
如果该目录中的模块将由特定用户专用于该用户运行的所有脚本(或者在以前的用例中,如果重新编译Perl不是更改默认@INC
的选项),请设置用户的PERL5LIB
,通常是在用户登录期间.
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.
注意:请注意通常的Unix环境变量陷阱-例如在某些情况下,以特定用户身份运行脚本并不能保证在该用户的环境设置下运行脚本,例如通过su
.
如果仅在特定情况下(例如,在开发/调试模式下执行脚本时)需要使用目录中的模块,则可以手动设置PERL5LIB
或通过
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.
如果仅需要将模块用于特定脚本,则使用它们的所有用户都应在程序本身中使用use lib
/no lib
编译指示.当需要在运行时动态确定要搜索的目录时也应使用它-例如通过脚本的命令行参数或脚本的路径(有关非常好的用例,请参见 FindBin 模块).
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).
如果需要根据某些复杂的逻辑来操作@INC
中的目录,那么通过结合使用use lib
/no lib
编译指示来实现它是不可能的,以至于太笨拙了,那么请在内部使用直接的@INC
操作BEGIN {}
块或在为@INC
操作指定的专用库中,必须在使用其他任何模块之前由脚本使用这些.
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.
一个例子是自动在prod/uat/dev目录中的库之间切换,如果dev和/或UAT中缺少瀑布库拾取,则在prod中使用瀑布库拾取(最后一个条件使得标准的"use lib + FindBin"解决方案相当复杂. 如何使用Beta Perl脚本中的Beta Perl模块? .
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?.
直接操作@INC
的另一个用例是能够添加子例程引用或对象引用(是的,弗吉尼亚州,@INC
可以包含自定义Perl代码,而不仅仅是目录名称,如<一个href ="https://stackoverflow.com/questions/2541119/when-is-a-subroutine-reference-in-inc-inc">> 何时在@INC中调用一个子例程引用? ).
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?).
这篇关于Perl的@INC是如何构造的? (又有什么方法可以影响搜索Perl模块的位置?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!