metacpan - perl mcpan
¿Cómo puedo verificar si tengo un módulo Perl antes de usarlo? (6)
Tengo el siguiente código Perl que se basa en Term::ReadKey
para obtener el ancho del terminal; A mi compilación de NetBSD le falta este módulo, por lo que quiero establecer el ancho del terminal por defecto en 80 cuando falta el módulo.
No puedo descifrar cómo usar un módulo de forma condicional, sabiendo de antemano si está disponible. Mi implementación actual simplemente se cierra 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. ¿Pueden ayudarme a implementar esto en mi script de manera más efectiva?
Aquí hay una solución escueta 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 debajo de esta! :-) que usan eval { use SomeModule }
son incorrectas porque las declaraciones de use
se evalúan en tiempo de compilación, independientemente de dónde aparezcan en el código. Entonces, si SomeModule
no está disponible, el script morirá inmediatamente después de la compilación.
(Una cadena eval de una sentencia de use
también funcionará ( eval ''use SomeModule'';
), pero no tiene sentido analizar y compilar código nuevo en tiempo de ejecución cuando el par require
/ import
hace lo mismo, y se comprueba la sintaxis en tiempo de compilación arrancar.)
Finalmente, tenga en cuenta que mi uso de eval { ... }
y $@
aquí es sucinto para el propósito de este ejemplo. En el código real, debe usar algo como Try::Tiny , o al menos estar al tanto de los problemas que aborda .
Consulte el módulo CPAN Module::Load::Conditional . Hará lo que quieras.
Creo que no funciona cuando se usan variables. Por favor, consulte este enlace que explica cómo se puede usar 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 la matriz @INC y se quejará de que no encuentre "Foo :: Bar" allí. En este caso puedes hacer:
eval "require $class";
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 cuando se ejecuta el script, en lugar de cuando se compila, y puede probar si tiene éxito o no y reaccionar de manera adecuada.
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) {
# ...
}
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::...
cargado correctamente.