如果我的 Perl 程序使用 Perl 模块,它将如何确定在哪里可以找到包含模块代码的文件?
例如,如果程序包含:
use MyModule1; # Example 1
use This::Here::MyModule2; # Example 2
它会在哪里看?
如果我的 Perl 程序使用 Perl 模块,它将如何确定在哪里可以找到包含模块代码的文件?
例如,如果程序包含:
use MyModule1; # Example 1
use This::Here::MyModule2; # Example 2
它会在哪里看?
Perl 解释器(它运行你的 perl 程序)将使用一个特殊的数组调用@INC
来搜索包含该模块的文件。
@INC
数组中的每个值都是一个目录名称(但请参见下面的注释);Perl 将使用下面指定的规则在循环中搜索这些目录。(有关如何确定 @INC 内容的详细信息,请参阅此 SO 帖子)。
如果用尽后没有找到模块的文件@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
可能还包含子例程引用和对象引用,它们按照自定义代码指定的方式加载模块,而不是按照上面 #2 逻辑中指定的目录执行查找。该功能似乎很少使用,本文假设整个@INC
仅包含目录。
让我们看一个具体的例子,假设你@INC
包含两个子目录:
("/usr/lib/perl", "/opt/custom/lib")
.
然后 Perl 会搜索如下:
==================================================== ========================= | 模块 | 试试# | 文件尝试 ==================================================== ========================= | 我的模块1 | 尝试 1 | /usr/lib/perl/MyModule1.pm | 我的模块1 | 尝试 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
-like 机制来导入 Perl 模块时,都会使用 @INC。这包括:
require
指令本身use MyModule
语句(相当于require+import)use base
(相当于 require+"push @ISA")-M
命令行参数虽然这并不能直接回答问题,但这里有一些简单的技术可以确定您要使用的模块文件的完整路径。
要从命令行查看@INC数组的默认内容以及许多其他信息:
perl -V
If you want to know the location of the Carp module:
perldoc -l Carp
Inside a script, printing the contents of the %INC hash is useful to determine the actual module you are using, especially if you have modified @INC from its default:
use Carp;
print $INC{'Carp.pm'};
This simple script can also be used to Find installed Perl modules matching a regular expression and to identify any duplicate modules in different directories.
使用模块列表
将一些语义从命名模块导入当前包,通常通过将某些子例程或变量名称别名到包中。它完全等同于
BEGIN { require Module; Module->import( LIST ); }
除了 Module 必须是一个裸词。
require
繁重的工作也是如此,require
文档提供
如果 EXPR 是一个裸词,则 require 会为您假定一个
".pm"
扩展名并在文件名中替换"::"
为"/"
,以便于加载标准模块。这种形式的模块加载不会改变您的命名空间。换句话说,如果你试试这个:
require Foo::Bar; # a splendid bareword
require 函数实际上会在数组
"Foo/Bar.pm"
中指定的目录中查找文件。@INC