从模块中导出子程序'使用'通过'要求'

时间:2015-01-19 23:59:33

标签: perl perl-module

我正在使用我们的构建系统编写的一组perl脚本。不幸的是,它们不是作为一组模块编写的,而是一堆.pl文件,它们需要'彼此。

对“LogOutput.pl”进行一些更改后。几乎所有其他文件都使用了这个文件,我开始遇到文件因多次需要而引起的一些问题。

为了解决这个问题,虽然没有更改每个文件(其中一些不在我的直接控制范围内),但我做了以下事情:

- 将LogOutput.pl中的所有内容移动到一个新文件LogOutput.pm,这个文件具有使其成为模块所需的一切(基于读取http://www.perlmonks.org/?node_id=102347)。

- 使用以下

替换现有的LogOutput.pl
BEGIN
{
    use File::Spec;

    push @INC, File::Spec->catfile($BuildScriptsRoot, 'Modules');
}

use COMPANY::LogOutput qw(:DEFAULT);

1;

这是有效的,除了我需要更改调用代码以使用新包为子名称添加前缀(即COMPANY :: LogOutput :: OpenLog而不仅仅是OpenLog)

我有什么方法可以从LogOutput.pl中导出新模块的子程序吗?

2 个答案:

答案 0 :(得分:2)

名为Import::Into的井可用于将模块的符号导出到另一个包中。

use Import::Into;

# As if Some::Package did 'use COMPANY::LogOutput'
COMPANY::LogOutput->import::into("Some::Package");

但是,这不是必要的。由于LogOutput.pl没有包,因此其代码位于所需的包中。 use COMPANY::LogOutput将导出到需要LogOutput.pl的包中。您编写的代码应该可以在.pl文件中模拟一堆函数。

这就是我认为LogOutput.pl的样子(使用子程序"传递"作为你在那里的任何子程序的代表)...

sub pass { print "pass called\n" }

1;

我认为LogOutput.pl和LogOutput.pm现在看起来像......

# LogOutput.pl
BEGIN
{
    use File::Spec;

    push @INC, File::Spec->catfile($BuildScriptsRoot, 'Modules');
}

use COMPANY::LogOutput qw(:DEFAULT);

1;


# LogOutput.pm
package test;

use strict;
use warnings;

use Exporter "import";

our @EXPORT_OK = qw(pass);
our %EXPORT_TAGS = (
    ':DEFAULT'    => [qw(pass)],
);

sub pass { print "pass called\n" }

1;

请注意,这不会改变require的基本性质。一个模块仍然只需要一次,之后再次要求它是一个无操作。所以这仍然无效......

{
    package Foo;

    require "test.pl";  # this one will work
    pass();
}

{
    package Bar;

    require "test.pl";  # this is a no-op
    pass();
}

你可以让它发挥作用。 Perl存储%INC中所需文件的列表。如果删除并输入,Perl将再次加载该文件。但是,您必须小心.pl文件中的所有代码都可以。 @INC hack必须确保它只运行一次。

BEGIN
{
    use File::Spec;

    # Only run this code once, no matter how many times this
    # file is loaded.
    push @INC, File::Spec->catfile($BuildScriptsRoot, 'Modules')
        if $LogOutput_pl::only_once++;
}

use COMPANY::LogOutput qw(:DEFAULT);

# Allow this to be required and functions imported more
# than once.
delete $INC{"LogOutput.pl"};

1;

这是全局变量合理的少数情况之一。必须声明一个词法(my)变量,并且每次加载库时都会重置该变量。全局变量不需要声明,并且在加载之间会持续存在。

答案 1 :(得分:0)

这对我来说只是一个愚蠢的错误,我没有把子进入@EXPORT列表,只进入@EXPORT_OK。