Perl - 包/模块问题

时间:2010-06-04 20:59:25

标签: perl perl-module

从我使用Perl模块阅读的所有内容中,基本用法是:

  • 带有.pm扩展名的模块文件,其中包含语句package <name>,其中<name>是没有扩展名的模块的文件名。
  • 使用模块的代码文件包含语句use <name>;

我正在编码的应用程序有一个主代码脚本,它使用大约5个模块。我忘记在模块中包含package <name>语句,但我的代码仍然可以使用use <name>语句运行。我开始在其中一个模块中收到Undefined subroutine错误,因此我将package语句添加到每个模块中。现在其余模块停止工作。是什么给了什么?

示例:

mainapp.pl

#!/usr/bin/perl
use UtyDate;
my $rowDate = CurrentDate("YYYYMMDD");

UtyDate.pm

#!/usr/bin/perl
package UtyDate;
sub CurrentDate
{
    #logic
}
return 1;

当我运行上面的代码时,我收到错误Undefined subroutine &main::CurrentDate called at...。但是,如果我从UtyDate.pm中删除package UtyDate;行,则不会出现错误。这种情况存在于几个但不是所有模块中。

显然有很多代码我没有展示,但我很困惑,我没有展示的任何代码可能会影响我在这里展示的包/使用结构。

4 个答案:

答案 0 :(得分:10)

使用模块时,模块中的代码在编译时运行。然后在模块的包名称上调用import。因此,use Foo;BEGIN { require Foo; Foo->import; }

相同

您的代码在没有package声明的情况下工作,因为所有代码都是在主应用程序代码使用的包main下执行的。

添加package声明后,它停止工作,因为您定义的子程序不再在main中定义,而是在UtyDate中定义。

您可以使用完全限定名称UtyDate::CurrentDate();访问子例程,也可以在use模块时将子例程导入当前名称空间。

UtyDate.pm

package UtyDate;
use strict;
use warnings; 

use Exporter 'import';

# Export these symbols by default.  Should be empty!    
our @EXPORT = ();

# List of symbols to export.  Put whatever you want available here.
our @EXPORT_OK = qw( CurrentDate  AnotherSub ThisOneToo );

sub CurrentDate {
    return 'blah';
}

sub AnotherSub { return 'foo'; }

主程序:

#!/usr/bin/perl
use strict;
use warnings; 

use UtyDate 'CurrentDate';

# CurrentDate is imported and usable.    
print CurrentDate(), " CurrentDate worked\n";

# AnotherSub is not
eval {  AnotherSub() } or print "AnotherSub didn't work: $@\n";

# But you can still access it by its fully qualified name
print UtyDate::AnotherSub(), " UtyDate::AnotherSub works though\n";

有关详细信息,请参阅Exporter文档。

答案 1 :(得分:3)

您缺少导出器perl标头代码。您需要在package语句下方的pm文件顶部添加以下内容:

package UtyDate;
BEGIN {
  use Exporter ();
  use vars qw($VERSION @ISA @EXPORT);
  $VERSION = "1.0.0";
  @ISA = qw(Exporter);
  @EXPORT = qw( &CurrentDate );
}

请参阅此链接:http://perldoc.perl.org/Exporter.html#DESCRIPTION

答案 2 :(得分:1)

除了格雷的建议,你可以这样做:

use UtyDate;
UtyDate::CurrentDate(...);

答案 3 :(得分:0)

除了使用导出器之外,正如Gray指出的那样,你可以(UGLY,但也可以)使用模块名称调用函数。

您的函数/过程不起作用,因为它们现在位于不同的命名空间(由模块名称定义)

use UtyDate;

UtyDate::CurrentDate(  )