2012-02-27 4 views
2

Есть ли способ загрузить целые модули во время выполнения на Perl? Я думал, что я нашел хорошее решение с autouse но следующий фрагмент кода не может компиляции:Автоматически загружать модули perl во время выполнения в Perl

пакет tryAutouse2;
использование autouse 'tryAutouse';
my $ obj = tryAutouse-> new();

Я полагаю, это потому, что autouse специально предназначен для использования с экспортируемых функций, я правильно? Так как это не удается компиляции, невозможно ли иметь пакетное решение? Я вынужден до require перед каждым вызовом нового модуля, если мне нужна динамическая загрузка?

Причина в том, что моя команда загружает много модулей, но мы боимся, что это есть память.

+3

Вы смотрели на [ 'Module :: Load'] (http://perldoc.perl.org/Module/Load.html) и [' Module :: Load :: Conditional'] (HTTP: //perldoc.perl.org/Module/Load/Conditional.html)? –

+0

Какое сообщение об ошибке вы получаете, когда не удается выполнить компиляцию? – Zaid

ответ

5

Вы хотите Class::Autouse или ClassLoader.

Из-за слишком большого количества магии я использую ClassLoader только в своем REPL для удобства. Для серьезного кода я всегда загружаю классы явно. Джек Мейни отмечает в комментарии, что Module::Load и Module::Load::Conditional подходят для отложенной загрузки.

+0

Именно то, что я хотел. Благодаря! – joslinm

1
eval 'use tryAutouse; 1;' or die [email protected]; 

Будет работать. Но вы можете скрыть уродство.

+0

@mob: Вы правы. Не будет работать 'eval {use ...}', но 'eval 'use ...'' will. Я удалю свой комментарий. –

4

Нет ничего плохого в использовании ИМО. Пропустить экспорт функции и просто вызвать полное имя:

require Some::Module; 
Some::Module::some_function(@some_arguments); 
1

Когда вы говорите:

use Foo::Bar; 

Вы загрузка модуля Foo::Bar в во время компиляции. Таким образом, если вы хотите загрузить свой модуль в во время выполнения, вы будете использовать require:

require Foo::Bar; 

Они рода эквивалентных, но есть и различие. См. Perldoc по адресу use, чтобы понять полную разницу. Например, используемая таким образом require не будет автоматически загружать импортированные функции. Это может быть важно для вас.

Если вы хотите проверить, есть ли модуль или нет, заверните свой оператор require в eval и проверьте, успешно ли eval.

Я использую подобную технику, чтобы увидеть, если конкретный модуль Perl доступен:

eval { require Mail::Sendmail; }; 
if ([email protected]) { 
    $watch->_Send_Email_Net_SMTP($watcher); 
    return; 
} 

В выше, я буду пытаться использовать Mail::Sendmail, который является дополнительным модулем, если он доступен.Если нет, то я запустить другую программу, которая использует Net::SMTP:

sub _Send_Email_Net_SMTP { 
    my $self = shift; 
    my $watcher = shift; 

    require Net::SMTP; #Standard module: It should be available 

WORD O'WARNING: Вы должны использовать фигурные скобки вокруг eval заявления, а не круглые скобки. В противном случае, если require не работает, ваша программа выйдет, что, вероятно, не то, что вы хотите сделать.

1

Инструкция «использование» выполняется во время компиляции, поэтому проверка пути к модулю также выполняется во время компиляции. Это может вызвать неправильное поведение, которое трудно понять, пока вы не рассмотрите содержимое массива @INC.

Одним из решений является добавление блока «BEGIN», но решение, показанное ниже, является неэлегантным.

BEGIN { unshift @INC, '/path/to/module/'; } 
use My::Module; 

Вы можете заменить весь беспорядок простую директиву:

use lib '/path/to/module'; 
use My::Module; 

Это работает, потому что выполняется во время компиляции. Итак, все готово для выполнения инструкции «use».

Вместо блока «BEGIN» вы также можете выбрать другую команду, выполняемую во время компиляции, т. Е. Объявление константы.

use constant LIB_DIR => '/path/to/module'; 
use lib LIB_DIR; 
use My::Module; 
Смежные вопросы