Как я могу проверить, есть ли у меня модуль 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 Вы можете помочь мне реализовать это в моем сценарии более эффективно?
6 ответов:
Вот простое решение, которое не требует другого модуля:
my $rc = eval { require Term::ReadKey; Term::ReadKey->import(); 1; }; if($rc) { # Term::ReadKey loaded and imported successfully ... }
Обратите внимание, что все ответы ниже (я надеюсь, что они ниже этого! :- ) что использование
eval { use SomeModule }
неверно, потому чтоuse
операторы вычисляются во время компиляции, независимо от того, где в коде они появляются. Таким образом, еслиSomeModule
недоступен, скрипт умрет сразу после компиляции.(строковое вычисление оператора
Наконец, обратите внимание, что мое использованиеuse
также будет работать (eval 'use SomeModule';
), но нет смысла разбирать и компилировать новый код на время выполнения, Когдаrequire
/import
pair делает то же самое, и синтаксис проверяется во время компиляции для загрузки.)eval { ... }
и$@
здесь кратко для целей этого примера. В реальном коде вы должны использовать что-то вроде Try::Tiny или, по крайней мере, знать о проблемах, которые он решает.
Проверьте модуль CPAN модуль::Load::Conditional . Он сделает то, что вы хотите.
Классический ответ (восходящий к Perl 4, по крайней мере, задолго до появления "use") состоял в том, чтобы "требовать ()" модуль. Это выполняется по мере выполнения сценария, а не при компиляции, и вы можете проверить на успех или неудачу и реагировать соответствующим образом.
И если вам требуется конкретная версия модуля:
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";