如何在Perl模块中包含数据文件?
将运行时所需的数据文件与Perl模块捆绑在一起的“正确”方式是什么,以便该模块可以在使用前读取其内容 一个简单的例子是这个Dictionary模块,它需要在启动时读取(单词、定义)对的列表如何在Perl模块中包含数据文件?,perl,perl-module,directory-structure,data-files,Perl,Perl Module,Directory Structure,Data Files,将运行时所需的数据文件与Perl模块捆绑在一起的“正确”方式是什么,以便该模块可以在使用前读取其内容 一个简单的例子是这个Dictionary模块,它需要在启动时读取(单词、定义)对的列表 package Reference::Dictionary; # TODO: This is the Dictionary, which needs to be populated from # data-file BEFORE calling Lookup! our %Dictionary; sub
package Reference::Dictionary;
# TODO: This is the Dictionary, which needs to be populated from
# data-file BEFORE calling Lookup!
our %Dictionary;
sub new {
my $class = shift;
return bless {}, $class;
}
sub Lookup {
my ($self,$word) = @_;
return $Dictionary{$word};
}
1;
和一个驱动程序Main.pl:
use Reference::Dictionary;
my $dictionary = new Reference::Dictionary;
print $dictionary->Lookup("aardvark");
现在,我的目录结构如下所示:
root/
Main.pl
Reference/
Dictionary.pm
Dictionary.txt
我似乎无法让Dictionary.pm在启动时加载Dictionary.txt。我已经尝试了一些方法来实现这一点,比如
- 使用开始块:
这也会失败,因为BEGIN在编译时执行,在数据可用之前执行BEGIN { open(FP, '<', 'Dictionary.txt') or die "Can't open: $!\n"; while (<FP>) { chomp; my ($word, $def) = split(/,/); $Dictionary{$word} = $def; } close(FP); }
- 硬编码模块中的数据
工作正常,但绝对不可维护our %Dictionary = ( aardvark => 'an animal which is definitely not an anteater', abacus => 'an oldschool calculator' ... );
这里有一个类似的问题:但它涉及的是由CPAN安装的模块,而不是像我试图做的那样与当前脚本相关的模块。没有必要在
开始时加载字典<代码>开始
时间与正在加载的文件有关。当您的main.pl
说use Dictionary
时,Dictionary.pm中的所有代码都被编译和加载。将代码提前加载到Dictionary.pm
package Dictionary;
use strict;
use warnings;
my %Dictionary; # There is no need for a global
while (<DATA>) {
chomp;
my ($word, $def) = split(/,/);
$Dictionary{$word} = $def;
}
你应该用哪一种<代码>数据更易于分发。一个独立的并行文件对于非编码人员来说更容易处理
与在加载库时加载整个词典相比,在需要时等待加载词典更为礼貌
use File::Basename;
# Load the dictionary from Dictionary.txt
sub _load_dictionary {
my %dictionary;
# Get the directory Dictionary.pm is located in.
my $dir = dirname(__FILE__);
open(my $fh, '<', "$dir/Dictionary.txt") or die "Can't open: $!\n";
while (<$fh>) {
chomp;
my ($word, $def) = split(/,/);
$dictionary{$word} = $def;
}
return \%dictionary;
}
# Get the possibly cached dictionary
my $Dictionary;
sub _get_dictionary {
return $Dictionary ||= _load_dictionary;
}
sub new {
my $class = shift;
my $self = bless {}, $class;
$self->{dictionary} = $self->_get_dictionary;
return $self;
}
sub lookup {
my $self = shift;
my $word = shift;
return $self->{dictionary}{$word};
}
使用File::Basename;
#从dictionary.txt加载字典
子加载字典{
我的字典;
#获取Dictionary.pm位于的目录。
my$dir=dirname(_文件__);
open(my$fh),我建议使用DATA
with,以确保在运行时之前对数据进行初始化。这也使其更易于自我记录
或者更适合使用UNITCHECK
块,该块将在库文件编译后立即尽早执行,因此可以被视为编译的扩展
package Dictionary;
use strict;
use warnings;
my %dictionary;
UNITCHECK {
while ( <DATA> ) {
chomp;
my ($k, $v) = split /,/;
$dictionary{$k} = $v;
}
}
包字典;
严格使用;
使用警告;
我的字典;
单位支票{
而(){
咀嚼;
我的($k,$v)=分割/,/;
$dictionary{$k}=$v;
}
}
请注意原型(即sub-new()
)除非你知道你在做什么,否则不要使用它们。如果你想让函数签名考虑,或者,我建议使用<代码>数据< /代码>用<代码> init <代码>,而不是<代码>开始<代码>,以确保数据在运行前被初始化。documenting@Schwern oops我的错,最近C/C++太多了!我将进行编辑以删除它们。您还应该避免在方法标识符中使用大写字母。它们是为Perl全局变量(如包名)保留的,因此您的子查找
应该是子查找
@Borodin大写方法名称没有保留。这不是正常的Perl样式,但它们是没有保留。
use File::Basename;
# Get the directory Dictionary.pm is located in.
my $dir = dirname(__FILE__);
open(my $fh, '<', "$dir/Dictionary.txt") or die "Can't open: $!\n";
my %Dictionary;
while (<$fh>) {
chomp;
my ($word, $def) = split(/,/);
$Dictionary{$word} = $def;
}
close($fh);
use File::Basename;
# Load the dictionary from Dictionary.txt
sub _load_dictionary {
my %dictionary;
# Get the directory Dictionary.pm is located in.
my $dir = dirname(__FILE__);
open(my $fh, '<', "$dir/Dictionary.txt") or die "Can't open: $!\n";
while (<$fh>) {
chomp;
my ($word, $def) = split(/,/);
$dictionary{$word} = $def;
}
return \%dictionary;
}
# Get the possibly cached dictionary
my $Dictionary;
sub _get_dictionary {
return $Dictionary ||= _load_dictionary;
}
sub new {
my $class = shift;
my $self = bless {}, $class;
$self->{dictionary} = $self->_get_dictionary;
return $self;
}
sub lookup {
my $self = shift;
my $word = shift;
return $self->{dictionary}{$word};
}
package Dictionary;
use strict;
use warnings;
my %dictionary;
UNITCHECK {
while ( <DATA> ) {
chomp;
my ($k, $v) = split /,/;
$dictionary{$k} = $v;
}
}