Perl `use qw` 或从 pm 文件导入子程序

Perl `use qw` or import subroutines from pm files

我有一个 perl 模块 .pm 文件,其中包含我的子程序,它看起来像这样:

package test;
use strict;
use vars qw($VERSION @ISA @EXPORT $ERROR $NAME);
require Exporter;
@ISA  = qw(Exporter);
@EXPORT = (
    sub1
    sub2
    err1
    err2
);
#...etc...

现在我有一个 pl 文件,需要导入子程序,但不是每个子程序,只要它们在配置列表中。例如:

@subs = ('sub1', 'sub2'); # need to load sub1 & sub2, but do not load err1 & err2

@subs = ('sub1', 'err1'); # need to load sub1 & err1, but do not load sub2 & err2

我该怎么做?

我尝试这样做,但没有成功:

my @subs = ('sub1', 'sub2');
use test @subs;

有没有办法只加载需要的功能?需要的是从 SQL 或配置文件或任何其他方式读取...

首先,所有的 Perl 全局变量都应该使用大写字母,所以你的包的名称应该以大写字母开头,并且文件名应该更改为符合

其次,如果不是从 Exporter 继承 ,而是直接加载它的 import 方法,那么开销会少得多

我不明白 err1err2 是什么东西,但应该把 optional exports 放在数组 @EXPORT_OK

这使您的模块看起来像这样

Test.pm

package Test;

use strict;
use warnings;

use Exporter 'import';

our @EXPORT_OK = qw/ sub1 sub2 /;

sub sub1 {
  print "sub1\n";
}

sub sub2 {
  print "sub2\n";
}

使用它的程序看起来像这样

use strict;
use warnings;

use Test qw/ sub1 /;

sub1;

输出

sub1

你的代码的原因:

my @subs = ('sub1', 'sub2');
use test @subs;

不起作用是 use 语句在解析过程中立即求值,在(几乎)任何其他代码之前。因此,您的代码的第二行实际上 运行s 之前,因此 @subs 在那一点上仍然是空的。

这个工作:

my @subs;
BEGIN { @subs = ('sub1', 'sub2'); }
use test @subs;

就像这样:

BEGIN {
    my @subs = ('sub1', 'sub2');
    require test;
    test->import(@subs);
}

在以前的版本中,BEGIN 块用于使对 @subs 的赋值已经在解析期间发生;在第二个版本中,整个代码被放在一个 BEGIN 块中,并且 use 语句被替换为它的 运行 时间等价物(require + import).


但是,您可能一开始就没有任何理由这样做。当你加载一个模块时,它的 all 代码无论如何都会被加载,* 所以你实际上并没有通过导入一些代码来节省任何内存模块提供的功能。事实上,不导入模块提供的所有内容的唯一真正原因是避免可能试图导出具有相同名称或您自己的函数的模块之间的冲突。

在任何情况下,总是可以* 调用模块中的函数而不导入它们,只需在它们前面加上模块名称和 ::。所以,而不是:

use test qw(foo bar);
foo();
bar();

你可以这样做:

use test ();
test::foo();
test::bar();

*) 从技术上讲,在 Perl 中 保证 的东西很少,并且模块很可能实现某种延迟加载导入函数时仅创建函数(或从另一个模块加载它们)的机制。但这需要自定义 import (and/or AUTOLOAD) 方法;对于使用 Exporter 的普通模块,上面的简化描述是正确的。