如果我的Perl程序使用了Perl模块,它将如何确定找到包含模块代码的文件?
例如,如果程序包含以下内容:
例如,如果程序包含以下内容:
use MyModule1; # Example 1
use This::Here::MyModule2; # Example 2
它会搜索哪里?
use MyModule1; # Example 1
use This::Here::MyModule2; # Example 2
它会搜索哪里?
@INC
的特殊数组来搜索包含模块的文件。
@INC
数组中的每个值都是一个目录名称(但请参见下面的注释); Perl将按照指定的规则在这些目录中循环搜索。 (有关如何确定@INC内容的详细信息,请参阅此SO帖子)。@INC
后未找到模块的文件,则程序的编译将中止并显示错误。 如果在@INC
指定的目录之一中找到了模块的文件,则搜索将在不查看其余@INC
的情况下结束。@INC
中的每个目录中搜索模块文件的方式如下: :: 分隔的单词),分为最后一个组件 - 用于形成文件名 - 和层次结构路径(前面的所有组件最后一个 :: )。如果模块名称仅有一个组件(没有 :: ,例如上面的 MyModule1 ),则层次结构路径为空,文件名是模块的名称。在这个问题的第二个例子中,最后一个组件是 MyModule2 ,层次结构路径将是 This :: Here 。
预期的文件名将通过将模块名称的最后一个组件附加到 .pm 扩展名来确定。例如,在我们的示例中, MyModule1.pm 和 MyModule2.pm 。
模块的目录将通过以下方式确定:
从 @INC 中获取下一个目录-以 / usr / lib / perl 作为示例
通过获取模块名称的层次结构路径(如果有)并将“ ::”替换为 / 或操作系统使用的任何字符作为目录分隔符来形成该目录的子目录。在我们的两个示例中,第一个模块将在 / usr / lib / perl (无子目录)中搜索,而第二个模块将在 / usr / lib / perl / This / Here 中搜索。
注意:模块名称在Unix和其他操作系统上显然区分大小写,其中文件/目录命名区分大小写。@INC 还可能包含子例程引用和对象引用,它们根据其自定义代码指定的方式加载模块,而不是按照#2逻辑中指定的目录执行查找。该功能似乎很少使用,并且本文假定整个 @INC 仅包含目录。
让我们看一个具体的例子,假设你的@INC
包含两个子目录:("/usr/lib/perl", "/opt/custom/lib")
。
那么Perl将按以下方式搜索:
==========================================================================
| 模块 | 尝试次数 | 尝试的文件
==========================================================================
| MyModule1 | 尝试 1 | /usr/lib/perl/MyModule1.pm
| MyModule1 | 尝试 2 | /opt/custom/lib/MyModule1.pm
==========================================================================
| This::Here::MyModule2 | 尝试 1 | /usr/lib/perl/This/Here/MyModule2.pm
| This::Here::MyModule2 | 尝试 2 | /opt/custom/lib/This/Here/MyModule2.pm
==========================================================================
请注意,一旦Perl在其中一个位置找到文件,它就会停止尝试搜索,而不会尝试查看文件是否在后续位置中存在。例如,如果/usr/lib/perl/This/Here/MyModule2.pm
存在,则Perl将不会查找也不关心/opt/custom/lib/This/Here/MyModule2.pm
的存在。
注意:每当Perl解释器使用类似于require
的机制导入Perl模块时,都会使用@INC。这包括:
require
指令本身
use MyModule
语句(相当于require+import)
use base
(相当于require+"push @ISA")
-M
命令行参数
perl -V
perldoc -l Carp
use Carp;
print $INC{'Carp.pm'};
这个简单的脚本也可以用于查找符合正则表达式的已安装Perl模块,并识别不同目录中的任何重复模块。
use
的文档:
use Module LIST
Imports some semantics into the current package from the named module, generally by aliasing certain subroutine or variable names into your package. It is exactly equivalent to
BEGIN { require Module; Module->import( LIST ); }
except that Module must be a bareword.
所以require
承担了繁重的工作,而require
文档提供了帮助。
If EXPR is a bareword, the require assumes a
".pm"
extension and replaces"::"
with"/"
in the filename for you, to make it easy to load standard modules. This form of loading of modules does not risk altering your namespace.In other words, if you try this:
require Foo::Bar; # a splendid bareword
The require function will actually look for the
"Foo/Bar.pm"
file in the directories specified in the@INC
array.