Perl模块能否“使用”其他Perl模块?

4

Linux上的Perl 5.24.0

Perl模块嵌套问题(有点类似)...... 我似乎无法让它正常工作,想知道问题出在哪里,希望能有人告诉我。下面这个简单的例子可以更好地表达我的问题...

首先是ping.pl...

#!/usr/bin/env perl
# This is ping.pl

use ping_mod;

ping_dbh();

exit;

接下来是Perl模块ping_mod.pm...
#!/usr/bin/env perl
use Exporter;
use ping_common;

package ping_mod;

@ISA = qw(Exporter);
@EXPORT = qw(ping_dbh);

sub ping_dbh {
    set_dbh();
    print "dbh = $dbh\n";
}

1;

最后是ping_mod使用的ping_common.pm...

#!/usr/bin/env perl
use Exporter;

our $dbh;

package ping_common;

@ISA = qw(Exporter);
@EXPORT = qw($dbh set_dbh);

sub set_dbh {
    $dbh = 99;
}

1;

当我运行ping.pl时,我得到以下输出...

Undefined subroutine &ping_mod::set_dbh called at ping_mod.pm line 11.

但是如果我将ping_mod.pm更改为...

#!/usr/bin/env perl
use Exporter;
use ping_common;

package ping_mod;

@ISA = qw(Exporter);
@EXPORT = qw(ping_dbh);

sub ping_dbh {
#    set_dbh();
#    print "dbh = $dbh\n";
    print "hi there\n";    
}

1;

……它运行得很好。因此,我认为它一定是成功导出的。但是"使用"ping_common会使它出现问题。

即使在ping.pl中"使用ping_common",它仍然找不到它。

1个回答

8

正如 @toolic 所说,use ping_common 必须在 package 语句之后。原因如下。

在 Perl 中,模块可以隔离全局变量和函数。实际上,ping_dbh 的完整名称是 ping_mod::ping_dbh。你可以在 ping_mod 包中调用 ping_dbh。如果你想在其他地方调用它,则必须使用其完整名称,即 ping_mod::ping_dbh

use Module 实际上是 require Module 将其加载,并使用 Module->import 将其函数和变量导入到当前包中。无论模块在何处加载,只要加载了就可以了。但是导入的位置非常重要。

有了这个理解,看看这个例子。

use ping_common;

package ping_mod;

这将会加载ping_common并导入其函数,不是到ping_mod中,而是到默认包main中。它们将不可用于ping_mod

package ping_mod;

use ping_common;

这也加载了 ping_common,但它将其函数导入到 ping_mod 中。

但是为什么 Exporter 在包外部仍然起作用呢?

use Exporter;
use ping_common;

package ping_mod;

@ISA = qw(Exporter);
@EXPORT = qw(ping_dbh);

具有讽刺意味的是,Exporter模块并不是通过导出来工作的,它是通过继承来实现的。@ISA = qw(Exporter); 语句使得 ping_mod 从 Exporter 中继承了 import 方法。因为这个语句位于 ping_mod 包中,所以 @ISA 这个全局变量就是 ping_mod::ISA
.pm 文件通常应该以一个 package 声明开始。尽管它不会产生任何影响,但是它们不应该以 #! 开始。 #! 告诉操作系统使用什么程序来运行文件作为可执行程序。Perl 模块通常不是可执行程序。
您可以在 perlmod 中了解更多关于包的信息

在这里使用的 Exporter 并不是通过导出来工作的。但是现在,当你可以使用 use Exporter 'import'; 代替子类化时,我认为再也没有理由去子类化它了。 - ysth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接