Как я могу проверить, есть ли у меня модуль Perl перед его использованием? - PullRequest
49 голосов
/ 30 октября 2008

У меня есть следующий код Perl, который полагается на Term::ReadKey, чтобы получить ширину терминала; В моей сборке NetBSD отсутствует этот модуль, поэтому я хочу установить ширину терминала по умолчанию равной 80, если модуль отсутствует.

Я не могу понять, как условно использовать модуль, заранее зная, доступен ли он. Моя текущая реализация просто завершается с сообщением о том, что не может найти Term::ReadKey, если он отсутствует.

#/usr/pkg/bin/perl -w
# Try loading Term::ReadKey
use Term::ReadKey;
my ($wchar, $hchar, $wpixels, $hpixels) = GetTerminalSize();
my @p=(2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97);
my $plen=$#p+1;
printf("num |".("%".int(($wchar-5)/$plen)."d") x $plen."\n",@p);

Я использую Perl 5.8.7 в NetBSD и 5.8.8 в CygWin Можете ли вы помочь мне реализовать это в моем сценарии более эффективно?

Ответы [ 6 ]

90 голосов
/ 31 октября 2008

Вот простейшее решение, которое не требует другого модуля:

my $rc = eval
{
  require Term::ReadKey;
  Term::ReadKey->import();
  1;
};

if($rc)
{
  # Term::ReadKey loaded and imported successfully
  ...
}

Обратите внимание, что все ответы ниже (я надеюсь, что они ниже этого! :-), которые используют eval { use SomeModule }, неверны, потому что use операторы оцениваются во время компиляции, независимо от того, где в коде они появляются. Так что, если SomeModule недоступен, скрипт умрет сразу после компиляции.

(Строка eval оператора use также будет работать (eval 'use SomeModule';), но нет смысла анализировать и компилировать новый код во время выполнения, когда пара require / import делает то же самое и является проверяется синтаксис во время компиляции для загрузки.)

Наконец, обратите внимание, что мое использование eval { ... } и $@ здесь кратко для целей этого примера. В реальном коде вы должны использовать что-то вроде Try :: Tiny или, по крайней мере, , чтобы знать о проблемах, которые он решает .

11 голосов
/ 30 октября 2008

Проверьте модуль CPAN Module :: Load :: Conditional . Он будет делать то, что вы хотите.

7 голосов
/ 31 октября 2008

Классический ответ (по крайней мере, задолго до Perl 4, задолго до появления «использования») заключался в том, чтобы «потребовать ()» модуль. Это выполняется при запуске сценария, а не при компиляции, и вы можете проверить его на успешность или неудачу и отреагировать соответствующим образом.

4 голосов
/ 05 мая 2009
if  (eval {require Term::ReadKey;1;} ne 1) {
# if module can't load
} else {
Term::ReadKey->import();
}

или

if  (eval {require Term::ReadKey;1;}) {
#module loaded
Term::ReadKey->import();
}

Примечание: 1; выполняется только если require Term::... загружен правильно.

4 голосов
/ 04 ноября 2008

А если вам требуется конкретная версия модуля:

my $GOT_READKEY;
BEGIN {
    eval {
        require Term::ReadKey;
        Term::ReadKey->import();
        $GOT_READKEY = 1 if $Term::ReadKey::VERSION >= 2.30;
    };
}


# elsewhere in the code
if ($GOT_READKEY) {
    # ...
}
0 голосов
/ 23 октября 2014

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

$class = 'Foo::Bar';
        require $class;       # $class is not a bareword
    #or
        require "Foo::Bar";   # not a bareword because of the ""

Функция require будет искать файл «Foo :: Bar» в массиве @INC и будет жаловаться, что не нашел там «Foo :: Bar». В этом случае вы можете сделать:

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