正如previous question中所建议的,延迟加载模块的一种方法是使用require
。我想延迟加载BerkeleyDB直到有必要,而不是每次我的应用程序运行时加载它。测试BerkeleyDB是否可用也很好。这是我的尝试,它似乎适用于我尝试的每个其他模块(调用脚本'load_bdb.pl'):
#!/usr/bin/env perl
use 5.010;
use strict;
use warnings;
my %hash;
eval {
require BerkeleyDB;
BerkeleyDB->import();
1;
} or do {
my $error = $@;
die "\nERROR: Couldn't load BerkeleyDB" if $error;
};
tie %hash, 'BerkeleyDB::Btree', -Filename => 'db_file', -Flags => DB_CREATE
or die "\nERROR: Could not open DBM file: db_file: $! $BerkeleyDB::Error\n";
这会产生以下错误:
在load_bdb.pl第18行使用“strict subs”时不允许使用Bareword“DB_CREATE”。 由于编译错误,load_bdb.pl的执行中止。
抑制错误并不能解决问题,因为我得到了:
名称“BerkeleyDB :: Error”仅使用一次:load_bdb.pl第20行可能的拼写错误。
错误:无法打开DBM文件:db_file:没有此类文件或目录
这告诉我,上面的require
和import
语句没有正确导入BerkeleyDB,而这适用于use
。那么,为什么require
无法使用这个特定的模块,还有其他解决方案吗?
答案 0 :(得分:2)
运行perl脚本时,执行会经历几个阶段。其中一个是编译。在编译期间,它会尝试解析诸如DB_CREATE之类的单词来决定它们是什么。如果BerkelyDB没有提前加载(由use
),那么第一次在tie语句中遇到它时,perl不知道它是什么。
在这种情况下,当你需要BerkelyDB时,它实际上是一个常量sub,稍后将被定义和导入。请注意,use
是编译时操作,而require
通常在运行时发生。为避免错误,你可以放一个&在名称前面,perl知道它实际上是一个sub(例如& DB_CREATE)
另一个警告,如果相似。您正在读取通常属于BerkeleyDB包的变量,但由于您没有加载它,除了在一个地方之外,该变量不会被引用。这导致perl认为它可能是你脚本中的拼写错误。
您可以通过将其设置为脚本顶部的某些内容(例如Undef)来解决此问题。