Загружать модули Perl автоматически во время выполнения в Perl - PullRequest
2 голосов
/ 27 февраля 2012

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

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

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

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

Ответы [ 5 ]

5 голосов
/ 27 февраля 2012

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

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

4 голосов
/ 27 февраля 2012

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

require Some::Module;
Some::Module::some_function(@some_arguments);
1 голос
/ 28 февраля 2012

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

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

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

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

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

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

use constant LIB_DIR => '/path/to/module';
use lib LIB_DIR;
use My::Module;
1 голос
/ 28 февраля 2012

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

use Foo::Bar;

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

require Foo::Bar;

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

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

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

eval { require Mail::Sendmail; };
if ($@) {
    $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 голос
/ 27 февраля 2012
eval 'use tryAutouse; 1;' or die $@;

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...