2014-05-30 5 views
0

Как было предложено в previous question, одним из способов задержки загрузки модулей было бы использовать require. Я хотел бы отложить загрузку BerkeleyDB, пока это не понадобится, вместо того, чтобы загружать ее каждый раз, когда запускается мое приложение. Было бы неплохо проверить, доступен ли BerkeleyDB. Вот моя попытка, которая, кажется, работает с любым другим модулем, я попытался (вызов сценария «load_bdb.pl»):Можно ли отложить загрузку BerkeleyDB?

#!/usr/bin/env perl 

use 5.010; 
use strict; 
use warnings; 

my %hash; 

eval { 
    require BerkeleyDB; 
    BerkeleyDB->import(); 
    1; 
} or do { 
    my $error = [email protected]; 
    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"; 

Это приводит следующее сообщение об ошибке:

Bareword "DB_CREATE" not allowed while "strict subs" in use at load_bdb.pl line 18. Execution of load_bdb.pl aborted due to compilation errors.

Подавляя ошибки делает не решить эту проблему, потому что я тогда получаю:

Name "BerkeleyDB::Error" used only once: possible typo at load_bdb.pl line 20.

ERROR: Could not open DBM file: db_file: No such file or directory

Это говорит мне, что require и import заявления выше, не импортируя BerkeleyDB сотрудничества Правильно, тогда как это отлично работает с use. Итак, почему require не работает с этим конкретным модулем и есть ли другое решение?

+0

Работает нормально. Проблема в том, что вы откладываете это, не задерживая компиляцию кода, требующего импорта. – ikegami

+0

@ikegami Я вижу проблему сейчас, но неясно, что вы подразумеваете под «задержкой компиляции кода, требующего импорта». Не могли бы вы уточнить или что вы имеете в виду и как это будет выглядеть? – SES

ответ

2

При запуске скрипта perl выполнение выполняется через несколько этапов. Одним из первых является компиляция. Во время компиляции он пытается разрешить такие слова, как DB_CREATE, чтобы решить, что они собой представляют. В случае, когда BerkelyDB не был загружен заранее (на use), то в первый раз, когда он встречается в заявке на связь, perl не знает, что это такое.

В этом случае это фактически постоянная подсистема, которая будет позже определена и импортирована, когда вам потребуется BerkelyDB. Обратите внимание, что use - это операция времени компиляции, а require обычно возникает во время выполнения. Чтобы избежать ошибки, вы можете поместить & перед именем, поэтому perl знает, что это фактически суб (например, & DB_CREATE)

Другое предупреждение, если оно аналогично. Вы читаете переменную, которая обычно относится к пакету BerkeleyDB, но поскольку вы ее не загружали, переменная не упоминается нигде, кроме одного места. Это заставляет perl думать, что это может быть опечатка в вашем скрипте.

Вы можете решить это, установив его на что-то (например, Undef) в верхней части скрипта.

+0

Хорошее объяснение. Я знаю, что 'use' по существу' require' и 'import' в блоке BEGIN, поэтому имеет смысл, почему ошибка компиляции возникает в коде выше. Последняя ошибка также понятна и сейчас. Если он не загружен во время компиляции, я полагаю, что оператор tie не знает, что делать с DB_CREATE (если вы не укажете, что это sub), так что это не сработает. – SES

Смежные вопросы