如果我的Perl程序使用Perl模块,它将如何确定在哪里找到包含模块代码的文件?
例如,如果程序包含:
use MyModule1; # Example 1
use This::Here::MyModule2; # Example 2
它会在哪里看?
答案 0 :(得分:13)
Perl解释器(运行你的perl程序)将使用一个名为@INC
的特殊数组来搜索包含该模块的文件。
@INC
数组中的每个值都是目录名称(,但请参阅下面的注释); Perl将使用下面指定的规则在循环中搜索这些目录。 (请参阅this SO post for details of how the contents of @INC are determined)。
如果在耗尽@INC
后未找到模块的文件,则程序的编译将中止并显示错误。如果在@INC
中指定的某个目录中找到模块的文件,则搜索完成后不会查看@INC
的其余部分。
Perl在@INC
中列出的每个目录中搜索模块文件的方式如下:
首先,它将模块名称的层次结构组件(由::
分隔的单词)分隔为最后一个组件(用于形成文件名)和层次结构路径(所有组件)在最后::
之前。
如果模块名称只有一个组件(没有::
,例如上面的MyModule1
),则层次结构路径为空,文件名是模块的名称。在此问题的第二个示例中,最后一个组件为MyModule2
,层次结构路径为This::Here
。
将通过附加.pm
扩展名的模块名称的最后一个组件来确定预期的文件名。例如。我们的例子中有MyModule1.pm
和MyModule2.pm
。
注意:在Unix和其他文件/目录命名区分大小写的操作系统上,模块名称显然区分大小写。
模块的目录将由以下人员确定:
从@INC
获取下一个目录 - 让我们说/usr/lib/perl
为例
通过获取模块名称的层次结构路径(如果有)并将“::”替换为/
或操作系统用作目录分隔符的任何字符来形成该目录的子目录。在我们的两个示例中,将在/usr/lib/perl
(无子目录)中搜索第一个模块,在/usr/lib/perl/This/Here
中搜索第二个模块。
注意:以上是一个小小的简化 - @INC
may also contain subroutine references and object references,它按照自定义代码指定加载模块,而不是在目录中执行查找如上面#2逻辑中所指定的那样。该功能似乎很少使用,本文假定整个@INC
仅包含目录。
让我们回顾一个具体的例子,假设你的@INC
包含两个子目录:
("/usr/lib/perl", "/opt/custom/lib")
。
然后Perl会搜索如下:
========================================================================== | Module | Try # | File to try ========================================================================== | MyModule1 | Try 1 | /usr/lib/perl/MyModule1.pm | MyModule1 | Try 2 | /opt/custom/lib/MyModule1.pm ========================================================================== | This::Here::MyModule2 | Try 1 | /usr/lib/perl/This/Here/MyModule2.pm | This::Here::MyModule2 | Try 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
(相当于要求+“推@ISA”)-M
命令行参数答案 1 :(得分:5)
虽然这不能直接回答这个问题,但这里有一些简单的技术来确定您要使用的模块文件的完整路径。
要从命令行查看@INC数组的默认内容以及许多其他信息,请执行以下操作:
perl -V
如果您想知道Carp模块的位置:
perldoc -l Carp
在脚本内部,打印%INC哈希的内容对于确定您正在使用的实际模块很有用,尤其是在您从默认值中修改了@INC时:
use Carp;
print $INC{'Carp.pm'};
这个简单的脚本也可以用于Find installed Perl modules matching a regular expression并识别不同目录中的任何重复模块。
答案 2 :(得分:2)
根据perlfunc documentation on use
:
使用模块列表
将一些语义从命名模块导入当前包,通常是将某些子例程或变量名称别名到包中。它完全等同于
BEGIN { require Module; Module->import( LIST ); }
除了Module必须是一个单词。
所以require
执行繁重的工作,require
documentation提供
如果EXPR是一个单词,则需要假定
".pm"
扩展名,并在文件名中替换"::"
"/"
,以便加载标准模块。这种加载模块的方式不会有改变命名空间的风险。换句话说,如果你试试这个:
require Foo::Bar; # a splendid bareword
require函数实际上会在
"Foo/Bar.pm"
数组中指定的目录中查找@INC
文件。