Как я могу проверить, есть ли у меня Perl-модуль, прежде чем использовать его?
Вопрос
У меня есть следующий 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";