【问题标题】:Exported Perl sub not found未找到导出的 Perl 子程序
【发布时间】:2012-08-30 17:44:30
【问题描述】:

我每隔一段时间就会遇到这个问题。出于某种原因,我在尝试调用导出的子程序时收到“未定义的子程序”错误,我不知道为什么,因为它似乎是在成熟的代码中突然发生的。

上次发生这种情况时,我想我使用了类似“package_2::exported_sub()”的东西。这一次有效,但它只是为 package_2 中的另一个子返回了一个错误。甚至把“使用package_2;”在上面的行没有帮助!我唯一能想到的是,导出的 sub 以某种方式未定义。

我的代码看起来有点像这样:

在文件 package_1.pm 中:

package package_1;

require Exporter;
@ISA = qw( Exporter );

@EXPORT = qw(
local_sub
);

use package_2;
use strict;
use warnings;
use diagnostics;

sub local_sub {
  &exported_sub;
}

在 package_2.pm 文件中:

package package_2;

require Exporter;
@ISA = qw( Exporter );

@EXPORT = qw(
exported_sub
);

use strict;
use warnings;
use diagnostics;

sub exported_sub {
 # do something
}

我束手无策...当这个弹出来时,我正在处理一张不相关的热票,明天开始用户测试!

提前致谢!


更新:

ikegami,感谢您的修复!不过我很好奇。我又遇到了这个问题,但这一次我没有找到循环依赖。我把它缩小到一行:

$row->{$attr} = ' ' unless ( $row->{$attr} );

显然,该行与使用或要求根本无关!我查看了 Apache 日志,但似乎没有什么特别突出的,但会努力解决我发现的任何问题。我也会看看我是否可以获得更多警告。

除此之外,下一步您有什么建议?

谢谢!

【问题讨论】:

  • 我忘了提到警告和诊断没有返回任何东西......我刚刚收到错误消息。
  • 您发布的代码非常适合我(使用简单的主程序use strist; use package_1; local_sub();,因此您应该尝试找出示例代码中缺少的内容以使其失败。
  • 问题似乎出在第一个“使用”的第三个文件上。注释掉“use”行解决了这个问题,所以我想知道这个文件是否有什么奇怪的地方,比如 DOS CR。我会继续挖掘!

标签: perl export undefined subroutine


【解决方案1】:

我怀疑你有一个循环依赖:package_1 使用 package_2 而 package_2 使用 package1(直接或间接)。

以下是我最初在 PerlMonks 上发布的解决方案:http://www.perlmonks.org/?node_id=778639


[ 需要使用这种技术是系统中设计缺陷的一个非常重要的指标,但我认识到资源并不总是可用于修复设计缺陷。 ]

如果ModA使用ModB,ModB使用ModA,ModA或ModB从对方导入符号,需要注意代码执行顺序。我发现避免问题的最佳方法是在加载任何其他模块之前设置 Exporter。

ModA.pm:

package ModA;

use strict;
use warnings;

BEGIN {
   our @ISA = qw( Exporter );
   our @EXPORT_OK = qw( ... );
   require Exporter;
}

use This;
use ModB;
use That;

...

1;

ModB.pm:

package ModB;

use strict;
use warnings;

BEGIN {
   our @ISA = qw( Exporter );
   our @EXPORT_OK = qw( ... );
   require Exporter;
}

use This;
use ModA;
use That;

...

1;

【讨论】:

  • 谢谢!我会试试看。
  • 这行得通,很抱歉,我还没有回复您确认。不幸的是,这是一个内部网页,我接管了超过 200 个 pm 文件,其中几个使用相同的实用程序文件。这会降低我的表现,还是可以忽略不计?
  • 性能将大大提高,因为您将获得代码以前没有执行过的性能。
【解决方案2】:

您确定您的use 行与use package_2 qw(xyz); 完全一样吗?

后者将定义 Exporter 的 import() 子例程将导出到调用者模块的内容。

【讨论】:

  • 是的,使用线很基础。
【解决方案3】:

我希望我的经验能适合你的情况。 Perl 包名必须用 Namespace 填写。 如果您的模块文件位于路径 $PERL_LIB/Fruit/Apple.pm 然后在模块文件中,必须指定Namespace Fruit::

package Fruit::Apple;

.......

如果你只写

package Apple;

.......

没有编译错误。但是当你在模块文件 Apple.pm 中调用你的方法时,会得到“未定义的子程序”错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-11
    • 1970-01-01
    • 2013-07-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多