通过 'require' 从模块 'used' 导出子程序
Exporting subroutines from a module 'used' via a 'require'
我正在使用一组编写我们的构建系统的 perl 脚本。不幸的是,它们不是作为一组模块编写的,而是一堆 'require' 彼此的 .pl 文件。
在对几乎所有其他文件都使用的 'LogOutput.pl' 进行一些更改后,我开始遇到一些由于文件被多次 'require'd 而引起的问题。
为了修复此问题,同时不更改每个文件(其中一些不在我的直接控制之下),我执行了以下操作:
-将 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 中导出新模块的子程序吗?
名为 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 的样子(使用子例程 "pass" 代替您在其中的任何子例程)...
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
黑客必须确保它只有 运行 一次。
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
) 变量,并且会在每次加载库时重置。全局变量不需要声明,并且会在加载之间持续存在。
结果证明这只是我的一个愚蠢错误,我没有将潜艇放入@EXPORT 列表,只放入@EXPORT_OK.
我正在使用一组编写我们的构建系统的 perl 脚本。不幸的是,它们不是作为一组模块编写的,而是一堆 'require' 彼此的 .pl 文件。
在对几乎所有其他文件都使用的 'LogOutput.pl' 进行一些更改后,我开始遇到一些由于文件被多次 'require'd 而引起的问题。
为了修复此问题,同时不更改每个文件(其中一些不在我的直接控制之下),我执行了以下操作:
-将 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 中导出新模块的子程序吗?
名为 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 的样子(使用子例程 "pass" 代替您在其中的任何子例程)...
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
黑客必须确保它只有 运行 一次。
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
) 变量,并且会在每次加载库时重置。全局变量不需要声明,并且会在加载之间持续存在。
结果证明这只是我的一个愚蠢错误,我没有将潜艇放入@EXPORT 列表,只放入@EXPORT_OK.