Un tema interesante, el de los errores. Se habló algo en la última YAPC::EU::2009. Incluso Larry Walll nos dió un divertido repaso sobre
los mensajes de error de los sistemas de antaño.
Tienes algo de información sobre la captura de errores, en la documentación de
eval().
Aquí tienes un ejemplo:
Using perl Syntax Highlighting
#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;
print "Antecedente...\n";
funcion_que_abre_fichero_inexistente();
print "Seguimos...\n";
sub funcion_que_abre_fichero_inexistente {
my $linea;
eval {
open my $FICHERO, q[<], 'Fichero_inexistente' or die "ERROR: No encuento al Fichero_inexistente\n";
$linea = <$FICHERO>;
close $FICHERO;
};
warn $@ if $@;
return $linea;
}
Coloreado en 0.002 segundos, usando
GeSHi 1.0.8.4
La salida es
Using text Syntax Highlighting
Antecedente...
ERROR: No encuento al Fichero_inexistente
Seguimos...
Coloreado en 0.000 segundos, usando
GeSHi 1.0.8.4
El die() ha capturado el error, pero la aplicación sigue funcionando.
En caso de no poner die(), la salida hubiera sido esta, por acción del warn():
Using text Syntax Highlighting
Antecedente...
readline() on closed filehandle $FICHERO at ./kk.pl line 17 (#1)
(W closed) The filehandle you're reading from got itself closed sometime
before now. Check your control flow.
Seguimos...
Coloreado en 0.000 segundos, usando
GeSHi 1.0.8.4
que es la descripción del error por haber intentado leer un fichero que aún no hemos abierto (línea 17).
Teniendo en cuenta que tanto open() como close() como cualquier otra operación de entrada y salida pueden provocar algún tipo de error, lo normal es usar el módulo
Fatal, que permite elevar una excepción en caso de que alguna de las funciones indicadas devuelva un valor undef, indicación de que algo fue mal:
Using perl Syntax Highlighting
#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;
use Fatal qw(open close);
print "Antecedente...\n";
funcion_que_abre_fichero_inexistente();
print "Seguimos...\n";
sub funcion_que_abre_fichero_inexistente {
my $linea;
if (open my $FICHERO, q[<], 'Fichero_inexistente') {
warn $! if $!;
$linea = <$FICHERO>;
close $FICHERO;
}
return $linea;
}
Coloreado en 0.002 segundos, usando
GeSHi 1.0.8.4
La salida es:
Using text Syntax Highlighting
Antecedente...
Uncaught exception from user code:
Can't open(GLOB(0x816e888), <, Fichero_inexistente): No existe el fichero o el directorio at (eval 2) line 3
main::__ANON__('GLOB(0x816e888)', '<', 'Fichero_inexistente') called at ./kk.pl line 17
main::funcion_que_abre_fichero_inexistente() called at ./kk.pl line 10
at (eval 2) line 3
main::__ANON__('GLOB(0x816e888)', '<', 'Fichero_inexistente') called at ./kk.pl line 17
main::funcion_que_abre_fichero_inexistente() called at ./kk.pl line 10
Coloreado en 0.000 segundos, usando
GeSHi 1.0.8.4
¡Boom!
Naturalmente, se puede capturar, con eval():
Using perl Syntax Highlighting
#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;
use Fatal qw(open close);
print "Antecedente...\n";
funcion_que_abre_fichero_inexistente();
print "Seguimos...\n";
sub funcion_que_abre_fichero_inexistente {
my $linea;
eval {
open my $FICHERO, q[<], 'Fichero_inexistente';
$linea = <$FICHERO>;
close $FICHERO;
};
warn $! if $!;
return $linea;
}
Coloreado en 0.002 segundos, usando
GeSHi 1.0.8.4
cuya salida es
Using text Syntax Highlighting
Antecedente...
Descriptor de fichero erróneo at ./kk.pl line 23.
Seguimos...
Coloreado en 0.000 segundos, usando
GeSHi 1.0.8.4
Vamos, que Fatal solo nos abrevia el no tener que poner die() en todas las funciones, de esta manera:
Using perl Syntax Highlighting
open my $FICHERO, q[<], 'Fichero_inexistente' or die;
$linea = <$FICHERO> or die;
close $FICHERO or die;Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
ya que todas esas operaciones pueden fallar. Pero necesitamos seguir capturándolas para tratar los errores, algo que podemos hacer con eval() y con módulos como el
Error, que remeda algunas de las funciones que vemos en otros lenguajes, como try() y catch().
En la última YAPC::EU::2009, Paul Fenwick nos recomendó usar su módulo
autodie y
autodie::exception (sí, el sombrero pirata lo llevó a la conferencia).
Using perl Syntax Highlighting
#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;
print "Antecedente...\n";
funcion_que_abre_fichero_inexistente();
print "Seguimos...\n";
sub funcion_que_abre_fichero_inexistente {
my $linea;
eval {
use autodie;
open my $FICHERO, q[<], 'Fichero_inexistente';
$linea = <$FICHERO>;
close $FICHERO;
};
if (my $E = $@) {
print "Ooops! ",$E->caller," tiene problemas: $@\n";
}
return $linea;
}
Coloreado en 0.002 segundos, usando
GeSHi 1.0.8.4
con lo que sale:
Using text Syntax Highlighting
Antecedente...
Ooops! main::funcion_que_abre_fichero_inexistente tiene problemas: Can't open 'Fichero_inexistente' for reading: 'No existe el fichero o el directorio' at ./kk.pl line 18
Seguimos...
Coloreado en 0.000 segundos, usando
GeSHi 1.0.8.4
Este módulo da toda la función relativa al fallo que ha ocurrido. Y así puedes decidir qué hacer. Aunque...
Using text Syntax Highlighting
bIlujDI' yIchegh()Qo'; yIHegh()!
It is better to die() than to return() in failure.
-- Klingon programming proverb.
Coloreado en 0.000 segundos, usando
GeSHi 1.0.8.4
(Paul nos dio otra conferencia sobre Perl/Klingon y el control de errores con autodie, vestido con su
uniforme de la flota estelar )