How do I test for an exception type in perl?
Asked Answered
P

1

8

How can I check what kind of exception caused the script or eval block to terminate? I need to know the type of error, and where the exception occurred.

Paternalism answered 1/3, 2010 at 9:57 Comment(1)
Related: #503689 and #2440466 and #2165661Helainehelali
H
13

The Perl way

Idiomatic Perl is that we are either ignoring all errors or capturing them for logging or forwarding elsewhere:

eval { func() };  # ignore error

or:

eval { func() };
if ($@) {
    carp "Inner function failed: $@";
    do_something_with($@);
}

or (using Try::Tiny - see that page for reasons why you might want to use it over Perl's built-in exception handling):

try { func() }
catch {
     carp "Inner function failed: $_";
     do_something_with($_);
};

If you want to check the type of exception, use regexes:

if ( $@ =~ /open file "(.*?)" for reading:/ ) {
    # ...
}

The line and file is also in that string too.

This is pretty nasty though, because you have to know the exact string. If you really want good error handling, use an exception module from CPAN.

Exception::Class

$@ doesn't have to be a string, it can be an object. Exception::Class lets you declare and throw exception objects Java-style. You can pass arbitrary information (filename, etc.) with the error when you throw it and get that information out using object methods rather than regex parsing - including the file and line number of the exception.

If you're using a third party module that does not use Error::Exception, consider

$SIG{__DIE__} = sub { Exception::Class::Base->throw( error => join '', @_ ); };

This will transform all errors into Exception::Class objects.

Error::Exception sets up proper stringification for Exception::Class objects.

Horsepower answered 1/3, 2010 at 10:21 Comment(2)
eval { blah }; if($@) { blah } is broken because $@ can be clobbered by object destructors. With eval { some_code(); 1 } or do { handle_exception() }; handle_exception is guaranteed to run, but $@ may be lost. There are still subtle traps to avoid. That's why, if you want simple exception handling, Try::Tiny is a good way to go. TT's docs go into ways that exception handling in Perl has issues. search.cpan.org/perldoc?Try::Tiny You may also want to read #2165661Ashburn
I've updated the answer to include Try::Tiny in case anyone new stumbles across this.Horsepower

© 2022 - 2024 — McMap. All rights reserved.