Как я могу проверить, есть ли у меня Perl-модуль, прежде чем использовать его?

StackOverflow https://stackoverflow.com/questions/251694

  •  05-07-2019
  •  | 
  •  

Вопрос

У меня есть следующий 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 Можете ли вы помочь мне более эффективно внедрить это в мой скрипт?

Это было полезно?

Решение

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

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 или хотя бы < a href = "http://search.cpan.org/dist/Try-Tiny/lib/Try/Tiny.pm#BACKGROUND" rel = "noreferrer"> быть в курсе проблем, которые он решает .

Другие советы

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

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

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

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) {
    # ...
}
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::... загружено должным образом.

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

$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";
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top