How can I check if I have a Perl module before using it?

perl module

29289 просмотра

6 ответа

I have the following Perl code which relies on Term::ReadKey to get the terminal width; My NetBSD build is missing this module, so I want to default the width of the terminal to 80 when the module is missing.

I can't figure out how to conditionally use a module, knowing ahead of time whether it is available. My current implementation just quits with a message saying it can't find Term::ReadKey if it's absent.

#/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);

I'm using Perl 5.8.7 on NetBSD and 5.8.8 on CygWin Can you help me implement this into my script more effectively?

Автор: dlamblin Источник Размещён: 12.11.2019 09:55

Ответы (6)


92 плюса

Решение

Here's a bare-bones solution that does not require another module:

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

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

Note that all the answers below (I hope they're below this one! :-) that use eval { use SomeModule } are wrong because use statements are evaluated at compile time, regardless of where in the code they appear. So if SomeModule is not available, the script will die immediately upon compiling.

(A string eval of a use statement will also work (eval 'use SomeModule';), but there's no sense parsing and compiling new code at runtime when the require/import pair does the same thing, and is syntax-checked at compile time to boot.)

Finally, note that my use of eval { ... } and $@ here is succinct for the purpose of this example. In real code, you should use something like Try::Tiny, or at least be aware of the issues it addresses.

Автор: John Siracusa Размещён: 30.10.2008 09:07

11 плюса

Check out the CPAN module Module::Load::Conditional. It will do what you want.

Автор: m0j0 Размещён: 30.10.2008 08:53

7 плюса

The classic answer (dating back to Perl 4, at least, long before there was a 'use') was to 'require()' a module. This is executed as the script is run, rather than when compiled, and you can test for success or failure and react appropriately.

Автор: Jonathan Leffler Размещён: 30.10.2008 09:23

4 плюса

And if you require a specific version of the module:

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) {
    # ...
}
Автор: Hinrik Размещён: 04.11.2008 10:35

4 плюса

if  (eval {require Term::ReadKey;1;} ne 1) {
# if module can't load
} else {
Term::ReadKey->import();
}

or

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

Note: the 1; only executes if require Term::... loaded properly.

Автор: ShqTth Размещён: 05.05.2009 06:43

0 плюса

I think it doesn't work when using variables. Please check this link which explains how it can be used with variable

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

The require function will look for the "Foo::Bar" file in the @INC array and will complain about not finding "Foo::Bar" there. In this case you can do:

 eval "require $class";
Автор: Utkarsh Kumar Размещён: 23.10.2014 12:45
Вопросы из категории :
32x32