小编典典

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

Per

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

例如,如果程序包含:

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

它会在哪里看?


阅读 293

收藏
2022-06-25

共1个答案

小编典典

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

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

如果用尽后没有找到模块的文件@INC,程序的编译会报错中止。如果在 中指定的目录之一中找到模块的文件@INC,则搜索完成,而不查看@INC.

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

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

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

  • 预期的文件名将通过在模块名称的最后一个组成部分附加.pm扩展名来确定。例如MyModule1.pmMyModule2.pm在我们的示例中。

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

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

  • 以下一个目录为例@INC-/usr/lib/perl比如说

  • 通过获取模块名称(如果有)的层次结构路径并将“::”替换/为操作系统用作目录分隔符的任何字符或任何字符来形成该目录的子目录。/usr/lib/perl在我们的两个示例中,将在(无子目录)中搜索第一个模块,在/usr/lib/perl/This/Here.
  • 注意:上面是一个轻微的简化 -@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-like 机制来导入 Perl 模块时,都会使用 @INC。这包括:

  • require指令本身
  • use MyModule语句(相当于require+import)
  • use base(相当于 require+”push @ISA”)
  • -M命令行参数
2022-06-25