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

时间:2010-02-01 22:30:55

标签: perl

Another question让我思考了不同的代码重用方法:userequiredo

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

perlfaq8涵盖了userequire之间的差异,但它没有提供任何有关偏好的建议(截至5.10 - 5.8.8 there is a quick bit of advice in favor of use)。

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

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

4 个答案:

答案 0 :(得分:68)

标准做法是大部分时间使用use,偶尔使用require,很少使用do

do 'file'将执行file作为Perl脚本。这几乎就像在文件内容上调用eval一样;如果您do多次使用同一个文件(例如在循环中),则每次都会对其进行解析和评估,这不太可能是您想要的。 doeval之间的区别在于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 Moduleuse Module类似,只是它在运行时发生,并且不会自动调用模块的import()方法。通常,您希望使用use尽早和可预测地失败,但有时候require会更好。例如,require可用于延迟仅偶尔需要的大型模块的加载或使模块可选。 (即,如果模块可用,则使用该模块,但如果不是,则使用该模块或减少功能。)

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

答案 1 :(得分:7)

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

阅读perldoc -f useperldoc -f require,了解详情。每perldoc -f use
useBEGIN { require Module; Module->import( LIST ); }相同,这更难看。

答案 2 :(得分:5)

主要区别在于进口/出口。当您使用模块时,首选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()过程,该过程通常用于设置模块。

有关详细信息,请参阅use的perldoc。

答案 3 :(得分:2)

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