¿Cómo puedo comprobar si tengo un módulo Perl antes de usarlo?


Tengo el siguiente código Perl que se basa en Term::ReadKey para obtener el ancho de la terminal; Mi compilación NetBSD no tiene este módulo, por lo que quiero predeterminar el ancho de la terminal a 80 cuando falta el módulo.

No puedo averiguar cómo usar condicionalmente un módulo, sabiendo de antemano si está disponible. Mi implementación actual acaba de salir con un mensaje que dice que no puede encontrar Term::ReadKey si está ausente.

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

Estoy usando Perl 5.8.7 en NetBSD y 5.8.8 en CygWin Puedes ayudar ¿implementar esto en mi guión de manera más efectiva?

 43
Author: thejartender, 2008-10-30

6 answers

Aquí hay una solución básica que no requiere otro módulo:

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

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

Tenga en cuenta que todas las respuestas a continuación (Espero que estén por debajo de esta! :- ) ese uso eval { use SomeModule } es incorrecto porque las sentencias use se evalúan en tiempo de compilación, sin importar en qué parte del código aparezcan. Así que si SomeModule no está disponible, el script morirá inmediatamente después de compilar.

(Una evaluación de cadena de una instrucción use también funcionará (eval 'use SomeModule';), pero no tiene sentido analizar y compilar nuevo código en tiempo de ejecución cuando el require/import pair hace lo mismo, y se comprueba la sintaxis en tiempo de compilación para arrancar.)

Finalmente, tenga en cuenta que mi uso de eval { ... } y $@ aquí es sucinto para el propósito de este ejemplo. En código real, deberías usar algo como Try::Tiny, o al menos ser consciente de los problemas que aborda.

 81
Author: John Siracusa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-16 13:20:03

Echa un vistazo al módulo CPAN Module::Load::Condicional. Hará lo que quieras.

 10
Author: m0j0,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-30 21:28:40

La respuesta clásica (que se remonta a Perl 4, al menos, mucho antes de que hubiera un 'uso') era 'requerir()' un módulo. Esto se ejecuta a medida que se ejecuta el script, en lugar de cuando se compila, y puede probar el éxito o el fracaso y reaccionar adecuadamente.

 6
Author: Jonathan Leffler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-30 21:23:59

Y si necesita una versión específica del módulo:

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) {
    # ...
}
 4
Author: Hinrik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-04 10:35:48
if  (eval {require Term::ReadKey;1;} ne 1) {
# if module can't load
} else {
Term::ReadKey->import();
}

O

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

Nota: el 1; solo se ejecuta si require Term::... se carga correctamente.

 4
Author: Jason Plank,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-18 01:21:19

Creo que no funciona cuando se usan variables. Por favor, compruebe este enlace que explica cómo se puede utilizar con variable

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

La función require buscará el archivo "Foo::Bar" en el array @INC y se quejará de no encontrar "Foo::Bar" allí. En este caso se puede hacer:

 eval "require $class";
 0
Author: Utkarsh Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-23 00:45:28