帮助从perl模块调用子例程并打印到日志文件

时间:2011-07-18 17:44:37

标签: perl

我不确定如何从perl模块中声明的子句调用另一个子例程。子程序只是获取日期信息。

我有一个文件句柄打开日志文件,我想打印一些日期信息到这个日志文件,但它不打印出来。我可以看到它触及文件,我也创建了日志文件-rwx。

以下是我正在调用的perl(Test.pm)模块中的示例子例程:

sub spGetCurDateTime {
    my ($sec, $min, $hour, $mday, $mon, $year) = localtime();
    my $currentDateTime = sprintf "%4d-%02d-%02d %02d:%02d:%02d",
        $year+1900, $mon+1, $mday, $hour, $min, $sec;
    return $curDateTime;
}

这是我的测试代码的一部分,我试图从(Test.pm)调用子程序

use Test.pm;

#Create log
open (LOG, ">/home/dev/test.log") || die "cannot append";

sub get_alert {
   undef $/;
   open (my $QFH, "< /home/dev/test.sql") or die "error can't open this file $!";
   print LOG "Checking on status time =>", &spGetCurDateTime, "\n";
   my $sth= $dbh->prepare(<$QFH>) ||
      die ("Cannot connect to the database: ".$DBI::errstr."\n");
   $sth->execute;
   close $QFH;
   my $row = $sth->fetchrow_hashref;
   $sth->finish;
   return $row->{RESULT};
   print $row;
}

3 个答案:

答案 0 :(得分:5)

首先,永远不要说&functionname,除非你知道为什么你可能想要魔术行为。通常在Perl 5中,函数调用看起来像functionname()functionname,具体取决于您是希望将其视为术语(即最高优先级)还是操作符(当您启动时更容易)我总是使用functionname()形式,因为这样可以达到预期目的。)

你可以说

print LOG "Checking on status time =>", Test::spGetCurDateTime(), "\n";

但是这可能会变老,所以大多数人使用Exporter模块将某些函数和变量导出到use Test;的名称空间中。您可能还希望避免使用模块名称Test,已经有module with that name

文件T.pm:

package T;

use strict;
use warnings;

use Exporter qw/import/;
our @EXPORT_OK = qw/spGetCurDateTime/;

sub spGetCurDateTime {
    my ($sec, $min, $hour, $mday, $mon, $year) = localtime;
    my $currentDateTime = sprintf "%4d-%02d-%02d %02d:%02d:%02d",
        $year+1900, $mon+1, $mday, $hour, $min, $sec;
    return $currentDateTime;
}

1;

在文件t.pl中:

#!/usr/bin/perl

use strict;
use warnings;

use T qw/spGetCurDateTime/;

print spGetCurDateTime(), "\n";

答案 1 :(得分:0)

阅读man perlmod。您需要将该函数作为导出符号,完全限定它,或者专门导入它...

答案 2 :(得分:0)

许多用户对Perl不了解的一件事是 namespace

如果不处理名称空间,就不可能像Perl模块的CPAN存档那样,因为每个模块都必须确保没有其他模块具有任何其他模块所具有的子程序和变量名。

以Perl编写的标准方式,每个Perl模块都有自己的命名空间。这样,变量名称和函数不会与您在程序中定义的变量和函数发生冲突。

看看你的测试模块,看看是否有一行:

package Test;

在程序的顶部。如果是,则表示模块中的每个变量,每个子例程都在Test的命名空间中,而不是您的main命名空间(默认命名空间)。 package命令将命名空间更改为下一个包命令。

如果(我们怀疑),您的Test.pm模块具有package命令,则需要将spGetCurDateTime子例程称为Test::spGetCurDateTime

正如已经指出的那样,您可以使用Exporter 变量和函数名称导入当前命名空间。

package Test;
use base qw(Exporter);

our @EXPORT qw(spGetCurDateTime log);

sub spGetCurDateTime {
};

在您的主程序中:

use Test;

将自动导入spGetCurDateTime和 log 子例程,您只需将它们用作spGetCurDateTime()log instead of Test :: spGetCurDateTime and Test :: log `。

但是,现在不鼓励默认导入所有子例程和变量,因为它可能会在没有警告的情况下干扰用户自己的程序。在上面的例子中,我不仅导入了log函数,而且还覆盖了Perl中内置的log函数(log取数字的自然对数)。

更好的是,使用EXPORT_OK并让用户选择他们想要导入的功能:

package Test;
use base qw(Exporter);

our @EXPORT_OK qw(spGetCurDateTime log);

sub spGetCurDateTime {
};

在您的主程序中:

use Test qw(spGetCurDateTime);

现在,您可以spGetCurDateTime()代替Test::spGetCurDateTime,但是您没有覆盖log而没有意识到这一点。您仍然可以说Test::log来执行模块中的log子例程。