题 在Perl中,使用模块比使用文件更好吗?


另一个问题 让我思考不同的代码重用方法: use 与 require 与 do

我在这里看到很多帖子,其中的问题围绕着使用 require 加载和执行代码。在我看来,这显然是一种不好的做法,但我没有找到任何有关我能指出的问题的好资源。

perlfaq8 涵盖了之间的区别 use 和 require,但它没有提供任何关于偏好的建议(截至5.10 - in 5.8.8有一些建议有利于使用)。

这个话题似乎缺乏讨论。我有几个问题需要讨论:

  1. Perl中首选的代码重用方法是什么?
    • use ModuleName;
    • require ModuleName;
    • require 'file.pl';
    • do 'file.pl';
  2. 有什么区别 require ModuleName 和 require "file.pl"
  3. 使用是否是个好主意 require "file.pl"?为什么或者为什么不?

49


起源


你的意思是 require Module 或者可能 do "file" 代替 require "file"? - Michael Carman
@迈克尔, require "file" 实际使用 do "file" 处理它的arugment,但它只会在给定的文件上运行一次。 - daotoad
@daotoad:那不是我要问的。通常 do 用于* .pl文件 require 用于* .pm文件。当然,文件扩展名无关紧要,但按照惯例* .pl长期以来并不意味着“perl库”。我试图澄清你是否指的是旧的用法,或者是否应修改问题以反映加载外部代码的三种方式(use, require,和 do)。在讨论中包括所有三种形式对我来说更有意义(对我而言)。 - Michael Carman
@Michael,是的,我的意思是旧式的用法。无论出于何种原因,我看到更多的人使用 require在SO上比我看到的使用 do。包括使用它确实有意义 do 在问题中。如果你对措辞有好主意,请编辑问题。目标是获得一个很好的资源来指导人们,而不是一遍又一遍地重写相同的响应(“使用模块”)。 - daotoad


答案:


标准做法是使用 use 大多数时候, require 偶尔,和 do 很少。

do 'file' 将执行 file 作为Perl脚本。这几乎就像打电话一样 eval 关于文件的内容;如果你 do 多次使用相同的文件(例如在循环中),每次都会对它进行解析和评估,这不太可能是你想要的。和...之间的不同 do 和 eval 就是它 do 无法在封闭范围内看到词法变量,这使得它更安全。 do 偶尔用于处理简单任务,例如处理以Perl代码形式编写的配置文件。

require 'file' 就好像 do 'file' 除了它只会解析任何特定文件一次,如果出现问题会引发异常。 (例如,找不到文件,它包含语法错误等)。自动错误检查使其成为一个很好的替代品 do 'file' 但它仍然只适用于相同的简单用途。

do 'file' 和 require 'file' 表单是* .pl文件扩展名为“Perl Library”的日子过去的遗留物。在Perl中重用代码的现代方法是将其组织到模块中。将某个东西称为“模块”而不是“库”只是语义,但这些词在Perl文化中意味着截然不同的东西。库只是子程序的集合;模块提供命名空间,使其更适合重用。

use Module 是使用模块代码的常规方法。注意 Module 包名称是一个裸字,而不是包含文件名的带引号的字符串。 Perl为您处理从包名到文件名的转换。 use 语句在编译时发生,如果失败则抛出异常。这意味着如果您的代码所依赖的模块不可用或无法加载,则错误将立即显现。另外, use 自动呼叫 import() 模块的方法,如果它有一个可以节省你一点点打字。

require Module 就好像 use Module 除了它在运行时发生并且不自动调用模块 import() 方法。通常你想使用 use早期和可预测地失败,但有时 require 更好。例如, require 可用于延迟仅偶尔需要的大型模块的加载或使模块可选。 (即,如果模块可用,则使用该模块,但如果不是,则使用该模块,或者减少功能。)

严格来说,唯一的区别 require Module 和 require 'file' 是第一种形式从包名称触发自动翻译 Foo::Bar 到像文件名 Foo/Bar.pm 而后一种形式需要一个文件名开头。但按照惯例,第一种形式用于加载模块,而第二种形式用于加载库。


65





使用时有一个主要的偏好 use,因为它发生在较早的状态 BEGIN {} 在编译期间,错误往往会在更合适的时间传播给用户。它也叫 sub import {} 使调用者能够控制导入过程的函数。这是大量使用的东西。通过调用特定的命名空间,您可以获得相同的效果 import,但这需要你知道命名空间的名称和文件,并编写对子程序的调用...这是更多的工作。反过来, use,只需要你知道命名空间,然后它需要具有匹配命名空间的文件 - 从而使命名空间和文件之间的链接对用户不那么有意识。

perldoc -f use,和 perldoc -f require, 了解更多信息。每 perldoc -f use
use 是相同的 BEGIN { require Module; Module->import( LIST ); } 哪个更难看。


6





主要区别在于进口/出口。 use 当您使用模块时,它是首选,因为它允许您指定要导入命名空间的例程:

use MyModule qw(foo bar baz); # allows foo(), bar() and baz() to be used

use MyModule qw(); # Requires explicit naming (e.g. MyModule::foo).

use 也给运行模块 import() 通常用于设置模块的过程。

请参阅perldoc 使用 了解更多细节。


5



实际上,他们是同一个人。在你的例子中 MyModule::import() 正在接受 qw(foo bar baz) 并自己做出口。它是同一个设施, Exporter,和 Sub::Exporter 只是生成一个 import()。 - Evan Carroll


运用 use to module将在编译期间包含模块,这会增加速度但使用更多内存,而使用 require 模块将包括在运行时。在需要时不需要使用导入模块需要使用更少的内存但会降低速度。


2