Perl 程序如何知道在哪里可以找到包含它使用的 Perl 模块的文件? [英] How does a Perl program know where to find the file containing Perl module it uses?

查看:23
本文介绍了Perl 程序如何知道在哪里可以找到包含它使用的 Perl 模块的文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

例如,如果程序包含:

使用 MyModule1;# 示例 1使用 This::Here::MyModule2;# 示例 2

它会在哪里看?

解决方案

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

@INC 数组中的每个值都是一个目录名称(但请参阅下面的注释);Perl 将使用下面指定的规则在这些目录中循环搜索.(请参考 this SO post 详细了解如何确定 @INC 的内容).

如果在用尽@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 也可能包含子例程引用和对象引用,它们按照自定义代码指定的方式加载模块,而不是按照#2中指定的方式在目录中执行查找上面的逻辑.该功能似乎很少使用,本文假设整个 @INC 仅包含目录.

让我们看一个具体的例子,假设你的 @INC 包含两个子目录:("/usr/lib/perl", "/opt/custom/lib").

然后 Perl 会搜索如下:

<前>==========================================================================|模块 |试试# |要尝试的文件==========================================================================|我的模块1 |尝试 1 |/usr/lib/perl/MyModule1.pm|我的模块1 |尝试 2 |/opt/custom/lib/MyModule1.pm==========================================================================|这个::这里::MyModule2 |尝试 1 |/usr/lib/perl/This/Here/MyModule2.pm|这个::这里::MyModule2 |尝试 2 |/opt/custom/lib/This/Here/MyModule2.pm==========================================================================

请记住,一旦 Perl 解释器在其中一个位置找到文件,它就会停止尝试搜索,而不会尝试查看该文件是否也在后面的位置.例如.如果 /usr/lib/perl/This/Here/MyModule2.pm 存在,那么 Perl 不会寻找,也不关心 /opt/custom/lib/This/的存在这里/MyModule2.pm.

注意:每当 Perl 解释器使用类似 require 的机制来导入 Perl 模块时,就会使用 @INC.这包括:

  • require 指令本身
  • use MyModule 语句(相当于 require+import)
  • 使用基础(相当于 require+"push @ISA")
  • -M 命令行参数

If my Perl program uses Perl modules, how will it determine where to find the file containing the module code?

For example, if the program contains:

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

where will it look?

解决方案

Perl interpreter (which runs your perl program) will use a special array called @INC to search for a file containing the module.

Each value in the @INC array is a directory name (but see note below); Perl will search within those directories in a loop using the rules specified below. (Please refer to this SO post for details of how the contents of @INC are determined).

If the module's file is not found after exhausting @INC, the program's compilation will be aborted with an error. If the module's file is found in one of the directories specified in @INC, the search is finished without looking at the rest of @INC.

The way Perl searches for a module file within each of the directories listed in @INC is as follows:

  • First, it will separate the module name's hierarchical components (words separated by ::), into the last component - which will be used to form a file name - and a hierarchy path (all the components preceding the last ::).

    In case the module name has only one component (no ::, e.g. MyModule1 above), the hierarchy path is empty and the filename is the name of the module. In the second example in this question, the last component is MyModule2 and hierarchy path will be This::Here.

  • The expected file name will be determined by appending the last component of the module name with a .pm extension. E.g. MyModule1.pm and MyModule2.pm in our examples.

    NOTE: Module names are obviously case sensitive on Unix and other operating systems where file/directory naming is case sensitive.

  • The module's directory will be determined by:

    1. Taking the next directory from @INC - let's say /usr/lib/perl as an example

    2. Forming a sub-directory of that directory by taking the hierarchy path of the module name (if any) and replacing "::" with / or whatever character the operating system uses as directory separator. In our two examples, the first module will be searched for in /usr/lib/perl (no sub-directory) and the second in /usr/lib/perl/This/Here.

    3. NOTE: the above is a slight simplification - @INC may also contain subroutine references and object references, which load the modules as their custom code specifies instead of performing the lookup in the directory as specified in #2 logic above. That functionality appears to be very seldom used and this article assumes that entire @INC only contains directories.

Let's go over a specific example, assuming that your @INC contains two sub-directories: ("/usr/lib/perl", "/opt/custom/lib").

Then Perl would search as follows:

==========================================================================
| 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
==========================================================================

Please recall that Perl interpreter will STOP trying to search once it finds the file in one of the locations, without trying to see if the file is in later locations as well. E.g. if /usr/lib/perl/This/Here/MyModule2.pm exists, then Perl will not look for, nor care about the existence, of /opt/custom/lib/This/Here/MyModule2.pm.

NOTE: @INC is used whenever Perl interpreter is using require-like mechanism for importing Perl modules. This includes:

  • require directive itself
  • use MyModule statement (equivalent to require+import)
  • use base (equivalent to require+"push @ISA")
  • -M command line parameter

这篇关于Perl 程序如何知道在哪里可以找到包含它使用的 Perl 模块的文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆