Perl Error Handling Module
Contents |
Q&A Tutorials Poetry RecentThreads NewestNodes Donate What'sNew on Jun 13, 2005 at 22:36UTC ( #466310=perlquestion: print w/replies, xml ) Need Help?? sgifford has asked for the wisdom of the Perl Monks concerning the following question: As seems to happen to all Perl programmers perl error variable eventually, I've been thinking about error handling in modules I code. It seems
Exception Handling In Perl Example
like I always start off just returning undef or using die, then after a while want to know more information die function in perl about why something failed, and end up writing some kind of half-assed error handling system, which I gradually expand. And this seems to be what everybody else does, so you have to wade perl error handling best practices through documentation to know whether a module has custom error handling code, uses variables like $! or $@, or just dies. I usually end up just writing things like: my $obj = Some::Object->new() or die "Couldn't create Some::object - $!\n"; [download] and plan on fixing it later, which only occasionally happens. die and eval solve part of this problem, but it's annoying to have to wrap
Perl Catch Die
every constructor and method call inside of an eval block, and in general die should only be used for truly unexpected and exceptional conditions, not simple errors that may happen from time to time. Realizing I was about to start coding another half-assed error handling system, I decided instead to try to put together something more flexible. My goals are: Modules should be able to use it with minimal headache Consistent and straightforward interface for module users. Possible to use in a thread-safe way Flexible I've posted the code for my fellow monks' consideration and comments. I used it for a module called Ekahau, so it's called Ekahau::ErrHandler; of course it would be renamed if I uploaded it to CPAN. Interface for Module Programmers To make this as simple as possible for module programmers, there are only 5 simple requirements: Inherit from Ekahau::ErrHandler Implement an ERROBJ method which returns the error object. Create an error handler object in the constructor. Inform the error handling module when the object is constructed, so it can store error methods in the object instead of in a class-wide variable. Indicate error with return $self->reterr("error message"), which will set the error m
A • B • C • D • E F • G • H • I • L M • N • O • P • S T • U • X die Perl 5 version 24.0 documentation Go to top Show recent pages Home > Language perl exit code reference > Functions > die Please note: Many features of this site require JavaScript. You perl error handling eval appear to have JavaScript disabled, or are running a non-JavaScript capable web browser. To get the best experience, please enable JavaScript or
Perl Handle Croak
download a modern web browser such as Internet Explorer 8, Firefox, Safari, or Google Chrome. Recently read die Perl functions A-Z | Perl functions by category | The 'perlfunc' manpage die LIST die raises an exception. Inside http://www.perlmonks.org/?node_id=466310 an eval the error message is stuffed into $@ and the eval is terminated with the undefined value. If the exception is outside of all enclosing evals, then the uncaught exception prints LIST to STDERR and exits with a non-zero value. If you need to exit the process with a specific exit code, see exit. Equivalent examples: die "Can't cd to spool: $!\n" unless chdir '/usr/spool/news'; chdir '/usr/spool/news' or die "Can't cd to spool: http://perldoc.perl.org/functions/die.html $!\n"If the last element of LIST does not end in a newline, the current script line number and input line number (if any) are also printed, and a newline is supplied. Note that the "input line number" (also known as "chunk") is subject to whatever notion of "line" happens to be currently in effect, and is also available as the special variable $. . See $/ in perlvar and $. in perlvar. Hint: sometimes appending ", stopped" to your message will cause it to make better sense when the string "at foo line 123" is appended. Suppose you are running script "canasta". die "/etc/games is no good"; die "/etc/games is no good, stopped";produce, respectively /etc/games is no good at canasta line 123. /etc/games is no good, stopped at canasta line 123.If the output is empty and $@ already contains a value (typically from a previous eval) that value is reused after appending "\t...propagated" . This is useful for propagating exceptions: eval { ... }; die unless $@ =~ /Expected exception/;If the output is empty and $@ contains an object reference that has a PROPAGATE method, that method will be called with additional file and line number parameters. The return value replaces the value in $@ ; i.e., as if $@ = eval { POD CPAN RT New 1 Open 0 View/Report Bugs Module Version: 0.17022 Source LatestRelease:Error-0.17024 NAME WARNING SYNOPSIS DESCRIPTION PROCEDURAL INTERFACE COMPATIBILITY CLASS INTERFACE CONSTRUCTORS STATIC METHODS OBJECT METHODS OVERLOAD METHODS PRE-DEFINED ERROR CLASSES Error::Simple $Error::ObjectifyCallback MESSAGE http://search.cpan.org/~shlomif/Error-0.17022/lib/Error.pm HANDLERS EXAMPLE SEE ALSO KNOWN BUGS AUTHORS MAINTAINER PAST MAINTAINERS COPYRIGHT NAME Error - Error/exception handling in an OO-ish way WARNING Using the "Error" module is no longer recommended due to the black-magical nature http://showmetheco.de/articles/2012/4/throwing-and-catching-exceptions-in-perl.html of its syntactic sugar, which often tends to break. Its maintainers have stopped actively writing code that uses it, and discourage people from doing so. See the "SEE ALSO" section below for better perl error recommendations. SYNOPSIS use Error qw(:try); throw Error::Simple( "A simple error"); sub xyz { ... record Error::Simple("A simple error") and return; } unlink($file) or throw Error::Simple("$file: $!",$!); try { do_some_stuff(); die "error!" if $condition; throw Error::Simple "Oops!" if $other_condition; } catch Error::IO with { my $E = shift; print STDERR "File ", $E->{'-file'}, " had a problem\n"; } except { my $E = shift; my $general_handler=sub {send_message $E->{-description}}; return perl error handling { UserException1 => $general_handler, UserException2 => $general_handler }; } otherwise { print STDERR "Well I don't know what to say\n"; } finally { close_the_garage_door_already(); # Should be reliable }; # Don't forget the trailing ; or you might be surprised DESCRIPTION The Error package provides two interfaces. Firstly Error provides a procedural interface to exception handling. Secondly Error is a base class for errors/exceptions that can either be thrown, for subsequent catch, or can simply be recorded. Errors in the class Error should not be thrown directly, but the user should throw errors from a sub-class of Error. PROCEDURAL INTERFACE Error exports subroutines to perform exception handling. These will be exported if the :try tag is used in the use line. try BLOCK CLAUSES try is the main subroutine called by the user. All other subroutines exported are clauses to the try subroutine. The BLOCK will be evaluated and, if no error is throw, try will return the result of the block. CLAUSES are the subroutines below, which describe what to do in the event of an error being thrown within BLOCK. catch CLASS with BLOCK This clauses will cause all errors that satisfy $err->isa(CLASS) to be caught and handled by eval messages and think that exceptions should be avoided at all cost, I will try to convert all exceptions to objects, create the base exception class and catch them with simple eval without using CPAN (blasphemy!). Throwing So we want this to behave the same: die 'error'; die MyException->new; And we do not want to write this every time (from perldoc die): use Scalar::Util "blessed"; eval { ... ; die Some::Module::Exception->new( FOO => "bar" ) }; if (my $ev_err = $@) { if (blessed($ev_err) && $ev_err->isa("Some::Module::Exception")) { # handle Some::Module::Exception } else { # handle all other possible exceptions } } We need to set up our own $SIG{__DIE__} handler: use Scalar::Util qw(blessed); $SIG{__DIE__} = sub { my ($e) = @_; return unless $^S; if (!blessed($e)) { $e =~ s/ at .*? line .*?\.//; chomp $e; $e = MyException->new(message => $e, caller => [caller]); } CORE::die($e); } The magic $^S variable tells us to skip eval parsing phase. We parse exception text because we still have to do it, in 2012! chomp is because we don't want this: something went wrong at myscript.pl line 42. Also we can save caller information for later use. Exception class package MyException::Base; use strict; use warnings; use overload '""' => sub { $_[0]->as_string }, 'bool' => sub {1}, fallback => 1; sub new { ... } sub as_string { my $self = shift; return sprintf("%s at %s line %s.", $self->{message}, $self->{path}, $self->{line}); } We can add also throw, rethrow, does and other methods for convenience. It is important to overload "" and bool because we want this to work: print $e; # and if ($e) { # we had an exception } Catching We can use Try::Tiny of course, but doing it with eval is as easy (and return works as expected!): eval { some_function(); 1; } || do { my $e = $@; if ($e->isa('MyException::FileNotFound')) { ... } else { ... } }; Assigning $@ to a local variable is important since sometimes $@ behaves strangely (should ask a Perl guru). See also Of course you can use Error (Jakub Narębski points out that it's not recommended and you should look for Exception::Class) and similar modules from CPAN instead of writing you own implementation, but sometimes... POD ERRORS Hey! The above document had some coding errors, which are explained below: Around line 118: Non-ASCII characte