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

DVK*_*DVK 13 perl perl-module path include

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

例如,如果程序包含:

use MyModule1;              # Example 1
use This::Here::MyModule2;  # Example 2
Run Code Online (Sandbox Code Playgroud)

它会在哪里看?

DVK*_*DVK 13

Perl解释器(运行你的perl程序)将使用一个特殊的数组@INC来搜索包含该模块的文件.

@INC数组中的每个值都是一个目录名(但请参阅下面的注释); Perl将使用下面指定的规则在循环中搜索这些目录.(有关如何确定@INC内容的详细信息,请参阅此SO帖子).

如果在耗尽后未找到模块的文件@INC,则程序的编译将中止并显示错误.如果在指定的目录之一中找到模块的文件@INC,则搜索完成而不查看其余部分@INC.

Perl在每个列出的目录中搜索模块文件的方式@INC如下:

  • 首先,它将模块名称的分层组件(由分隔的单词::),最后一个组件(将用于形成文件名)和层次结构路径(最后一个组件之前的所有组件)分开::.

    如果模块名称只有一个组件(::例如,MyModule1上面没有),则层次结构路径为空,文件名是模块的名称.在此问题的第二个示例中,最后一个组件是MyModule2层次结构路径This::Here.

  • 将通过附加.pm扩展名模块名称的最后一个组件来确定预期的文件名.例如MyModule1.pm,MyModule2.pm在我们的例子中.

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

  • 该模块的目录将由以下因素确定:

    1. 以下一个目录为例@INC- 让我们/usr/lib/perl举个例子

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

    3. 注意:上面是略微简化 - @INC 可能还包含子程序引用和对象引用,它们按照自定义代码指定加载模块,而不是在上面#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 命令行参数

  • 值得注意的是@INC的内容来自哪里.这甚至可能是OP正在寻找的答案.简要概述:主要的默认内容是内置的(显然,路径的确切细节取决于您的安装).在脚本之外修改它的主要方法是设置环境变量PERL5LIB(以冒号分隔的路径列表)或在运行时为可执行文件提供`-I/path/to/dir`选项.(这些前置于数组) (2认同)

too*_*lic 5

虽然这不能直接回答这个问题,但这里有一些简单的技术可以确定您想要使用的模块文件的完整路径.

要从命令行查看@INC数组的默认内容以及许多其他信息,请执行以下操作:

perl -V      
Run Code Online (Sandbox Code Playgroud)

如果您想知道Carp模块的位置:

perldoc -l Carp
Run Code Online (Sandbox Code Playgroud)

在脚本内部,打印%INC哈希的内容对于确定您正在使用的实际模块很有用,尤其是在您从默认情况下修改了@INC时:

use Carp;
print $INC{'Carp.pm'};
Run Code Online (Sandbox Code Playgroud)

此简单脚本还可用于查找与正则表达式匹配的已安装Perl模块,并识别不同目录中的任何重复模块.