Perl程序如何知道在哪里找到包含它使用的Perl模块的文件?

时间:2010-03-26 20:28:59

标签: perl path include perl-module

如果我的Perl程序使用Perl模块,它将如何确定在哪里找到包含模块代码的文件?

例如,如果程序包含:

use MyModule1;              # Example 1
use This::Here::MyModule2;  # Example 2

它会在哪里看?

3 个答案:

答案 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.pmMyModule2.pm

    注意:在Unix和其他文件/目录命名区分大小写的操作系统上,模块名称显然区分大小写。

  • 模块的目录将由以下人员确定:

    1. @INC获取下一个目录 - 让我们说/usr/lib/perl为例

    2. 通过获取模块名称的层次结构路径(如果有)并将“::”替换为/或操作系统用作目录分隔符的任何字符来形成该目录的子目录。在我们的两个示例中,将在/usr/lib/perl(无子目录)中搜索第一个模块,在/usr/lib/perl/This/Here中搜索第二个模块。

    3. 注意:以上是一个小小的简化 - @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文件。