我正在使用我们的构建系统编写的一组perl脚本。不幸的是,它们不是作为一组模块编写的,而是一堆.pl文件,它们需要'彼此。
对“LogOutput.pl”进行一些更改后。几乎所有其他文件都使用了这个文件,我开始遇到文件因多次需要而引起的一些问题。
为了解决这个问题,虽然没有更改每个文件(其中一些不在我的直接控制范围内),但我做了以下事情:
- 将LogOutput.pl中的所有内容移动到一个新文件LogOutput.pm,这个文件具有使其成为模块所需的一切(基于读取http://www.perlmonks.org/?node_id=102347)。
- 使用以下
替换现有的LogOutput.plBEGIN
{
use File::Spec;
push @INC, File::Spec->catfile($BuildScriptsRoot, 'Modules');
}
use COMPANY::LogOutput qw(:DEFAULT);
1;
这是有效的,除了我需要更改调用代码以使用新包为子名称添加前缀(即COMPANY :: LogOutput :: OpenLog而不仅仅是OpenLog)
我有什么方法可以从LogOutput.pl中导出新模块的子程序吗?
答案 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。