在Perl中,为什么我在perl模块中获得“未定义的子例程”但不在main中?

问题描述 投票:0回答:4

我在下面的代码中为sub2获取了一个“未定义的子例程”,但是没有为sub1。

这是perl脚本(try.pl)......

#!/usr/bin/env perl

use strict;
use IO::CaptureOutput qw(capture_exec_combined);

use FindBin qw($Bin);
use lib "$Bin";
use try_common;

print "Running try.pl\n";
sub1("echo \"in sub1\"");
sub2("echo \"in sub2\"");

exit;

sub sub1 {

(my $cmd) = @_;

print "Executing... \"${cmd}\"\n";
my ($stdouterr, $success, $exit_code) = capture_exec_combined($cmd);
print "${stdouterr}\n";

return;
}

这是try_common.pm ......

#! /usr/bin/env perl

use strict;
use IO::CaptureOutput qw(capture_exec_combined);

package try_common;

use Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(
  sub2
);

sub sub2 {

    (my $cmd) = @_;

    print "Executing... \"${cmd}\"\n";
    my ($stdouterr, $success, $exit_code) = capture_exec_combined($cmd);
    print "${stdouterr}\n";

    return;
}

1;

当我运行try.pl时,我得到......

% ./try.pl
Running try.pl
Executing... "echo "in sub1""
in sub1

Executing... "echo "in sub2""
Undefined subroutine &try_common::capture_exec_combined called at 
/home/me/PERL/try_common.pm line 20.

这看起来像某种范围问题,因为如果我剪切/粘贴“使用IO :: CaptureOutput qw(capture_exec_combined);”作为sub2的第一行,它的工作原理。这在try.pl中是不必要的(它运行sub1 OK),但perl模块中存在问题。 Hmmmm ....

在此先感谢您的帮助!

perl
4个回答
6
投票

您在声明包之前通过capture_exec_combined子句导入了use,因此它被导入到main包中,而不是try_common。进一步向上移动包声明。


4
投票

您应该查看perlmod文档以了解模块的工作原理。简而言之:

  1. 当您使用package A(在Perl 5中)时,您将以下代码的名称空间更改为A,并且该点之后的所有全局符号(例如子例程)定义将进入该包。无需导出范围内的子例程,并且可以在其范围名称前面使用:A::function。你似乎找到了这个。
  2. Perl使用package作为在不同文件中创建模块和拆分代码的方法,但也作为其面向对象特征的基础。
  3. 大多数情况下,模块由称为Exporter的特殊核心模块处理。见Exporter。该模块使用一些变量来知道该做什么,比如@EXPORT@EXPORT_OK@ISA。第一个定义了当您使用use Module包含模块时默认情况下应导出的名称。第二个定义了可以导出的名称(但需要用use Module qw(name1 name2)来提及。最后以面向对象的方式告诉你的模块是什么。如果你不关心面向对象,你的模块通常是“Exporter”。

另外,如另一个答案所述,当你定义一个模块时,package module声明应该是文件中的第一个东西,因此它之后的任何东西都将在该范围之内。


0
投票

当我犯这个错误时我讨厌,虽然我不再那么做了。你可以养成两种习惯:

最有可能的是,将整个文件作为包。第一行将是package语句,文件中不会显示其他package语句。

或者,使用新的PACKAGE BLOCK语法并将该包的所有内容放在块中。我这样做是为了我可能只在本地需要的小类:

package Foo {
    # everything including use statements go in this block
    }

-1
投票

我想我明白了。如果在perl模块中,我使用“::”作为“capture_exec_combined”的前缀,则它可以工作。

仍然,为什么主要的,try.pl不需要这个?

© www.soinside.com 2019 - 2024. All rights reserved.