【问题标题】:Can perl modules "use" other perl modules?perl 模块可以“使用”其他 perl 模块吗?
【发布时间】:2020-04-07 15:52:47
【问题描述】:

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”,它仍然找不到。

【问题讨论】:

    标签: perl


    【解决方案1】:

    正如@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,而是导入默认包mainping_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 方法。那个@ISA,因为它在ping_mod包中,所以是全局变量@ping_mod::ISA


    .pm 文件通常应以package 语句开头。他们不应该以#! 开头;虽然它不会伤害任何东西。 #! 告诉操作系统使用什么来将文件作为可执行程序运行。 Perl 模块通常不是可执行文件。

    你可以阅读更多关于packages in perlmod的信息。

    【讨论】:

    • 此处使用的导出器无法通过导出来工作。但是现在当你可以只做use Exporter 'import'; 而不是继承它时,我认为没有理由再继承它。
    猜你喜欢
    • 2012-07-26
    • 2012-07-04
    • 2011-09-23
    • 2010-10-02
    • 2012-02-12
    • 2015-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多