【问题标题】:Can't find exported subroutine in Perl在 Perl 中找不到导出的子例程
【发布时间】:2018-07-05 14:33:32
【问题描述】:

我有一个名为Utilities.pm 的模块。它导出一个名为dummy_method 的子例程。

package Foo::Utilities;

use strict;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);

require Exporter;

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

sub dummy_method {
  # do things
}

我有一个使用 dummy_method 子例程的 Perl 脚本:

use strict;
use warnings;

use Foo::Utilities qw('dummy_method');

my $foo = Foo::Utilities::dummy_method("foo");
print("$foo\n");

执行该脚本会引发导出错误:

Foo::Utilities 模块不导出“dummy_method”
在 /home/me/foo.pl 第 3 行出现导入错误后无法继续
BEGIN 失败——编译在 /home/me/foo.pl 第 3 行中止。

我很困惑,因为我用@EXPORT = qw(dummy_method); 明确地导出了那个子例程。如何在另一个脚本中使用dummy_method

【问题讨论】:

  • 您的问题令人困惑。您的模块导出dummy_method,但您尝试导入并运行some_method,它甚至不存在。请注意,一旦您正确导入了子例程,就不需要完全限定它:some_method('foo') 就可以了。
  • @Borodin 这是一个错字 - 这是固定的。
  • 我希望你能复制并粘贴你的真实代码和错误。
  • 鲍罗丁说过的话。您以重要的方式更改了错误消息。或者改代码。我们无法确定。始终始终复制并粘贴您的实际代码和错误。
  • @alex 是的,你做到了。我怀疑原始消息是否包含 either some_methoddummy_method。在你修改它之前和之后它肯定不会是正确的。

标签: perl


【解决方案1】:

有些人痴迷于将 qw 用于导入列表,即使只有一个元素。我认为这让其他人认为这是一项要求,而这只是列出清单的一种方式。

use Foo::Utilities qw('dummy_method');

说要导入一个名为'dummy_method' 的方法,而不是dummy_method,就像print qw('dummy_method') 打印'dummy_method',而不是dummy_method

试试吧:

use Foo::Utilities 'dummy_method';

或者,如果你必须:

use Foo::Utilities qw(dummy_method);

虽然您默认导出它,但您可以这样做:

use Foo::Utilities;

或者,由于您将其称为 Foo::Utilities::dummy_method,因此默认情况下甚至不导出它:

use Foo::Utilities ();

【讨论】:

  • “有些人痴迷于将qw 用于导入列表,即使只有一个元素” 确实如此,即使是这里的那些应该更了解的人。我的想法是,它可以更简单地添加或减少导入的标识符列表(在列表末尾留下一个尾随逗号),但它使单个项目的导入更加嘈杂和丑陋。
  • 这是一个很好的建议——但在这两种情况下我仍然得到一个错误,说子例程没有从父 Perl 模块导出。
  • @alex:那么你的代码还有其他问题,你已经从你发布的内容中删除了。我们无法帮助您。
  • Re "有些人痴迷于使用 qw 导入列表",一致性是可读代码的关键!
  • 这是可读性的众多好处之一。 :) 我不认为人们认为一个好的做法是强制性的。我认为将括号放在要使用/导入的一个参数周围并不比将括号放在其他任何参数周围更愚蠢。此外,每天的可读性都胜过一点愚蠢。
【解决方案2】:

您编写的代码经过ysth 建议的修改后可以正常工作。我能想到的唯一剩下的可能性是您错误地命名或定位了您的模块

use Foo::Utilities 'dummy_method'

将加载一个名为Foo/Utilities.pm 的文件,其中Foo 目录位于@INC 中的路径之一中。省略必须在模块路径中的初始目录是一个常见错误,并且您确实说您的模块仅称为Utilities.pm

还必须有一个行为不同的Foo/Utilities.pm,否则use 语句即使找不到文件也会失败

我已经用更现代的 Perl 编写了您的代码。这也有效

Foo/Utilities.pm

package Foo::Utilities;

use strict;
use warnings 'all';

use Exporter 'import';

our @EXPORT = qw(dummy_method);

sub dummy_method {
  print "dummy_method()\n";
  'do things';
}

main.pl

use strict;
use warnings;

use Foo::Utilities 'dummy_method';

my $foo = dummy_method('foo');

print("$foo\n");

不再需要使用vars,从Perl v5.8.7 开始导入 Exporter 中的import 方法(而不是继承它)会更好

【讨论】:

  • 还必须有一个行为不同的 Foo/Utilities.pm,否则即使找到文件,use 语句也会失败这就是我的问题的解决方案。在我的 $PERL5LIB 环境变量中,旧版本的 Utilities.pm 文件优先于新版本,导致 Perl 使用错误的模块(因此出现“缺少导出”错误)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-28
相关资源
最近更新 更多