是否可以延迟加载BerkeleyDB?

时间:2014-05-30 11:20:35

标签: perl berkeley-db

正如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:没有此类文件或目录

这告诉我,上面的requireimport语句没有正确导入BerkeleyDB,而这适用于use。那么,为什么require无法使用这个特定的模块,还有其他解决方案吗?

1 个答案:

答案 0 :(得分:2)

运行perl脚本时,执行会经历几个阶段。其中一个是编译。在编译期间,它会尝试解析诸如DB_CREATE之类的单词来决定它们是什么。如果BerkelyDB没有提前加载(由use),那么第一次在tie语句中遇到它时,perl不知道它是什么。

在这种情况下,当你需要BerkelyDB时,它实际上是一个常量sub,稍后将被定义和导入。请注意,use是编译时操作,而require通常在运行时发生。为避免错误,你可以放一个&在名称前面,perl知道它实际上是一个sub(例如& DB_CREATE)

另一个警告,如果相似。您正在读取通常属于BerkeleyDB包的变量,但由于您没有加载它,除了在一个地方之外,该变量不会被引用。这导致perl认为它可能是你脚本中的拼写错误。

您可以通过将其设置为脚本顶部的某些内容(例如Undef)来解决此问题。