How to properly use the try catch in perl that error.pm provides?

84,933

Solution 1

You're probably better off using Try::Tiny which will help you avoid a number of pitfalls with older perls.

use Try::Tiny;

try {
        die "foo";
} catch {
        warn "caught error: $_";
};

Solution 2

Last I checked, Error was deprecated. But here's how you would do it without that module:

eval {
    die "Oops!";
    1;
} or do {
    my $e = $@;
    print("Something went wrong: $e\n");
};

Basically, use eval instead of try, die instead of throw, and look for the exception in $@. The true value at the end of the eval block is part of an idiom to prevent $@ from unintentionally changing before it is used again in Perl versions older than 5.14, see P::C::P::ErrorHandling::RequireCheckingReturnValueOfEval for details. For example, this code suffers from this flaw.

# BAD, DO NOT USE WITH PERLS OLDER THAN 5.14
eval {
    die "Oops!";
};
if (my $e = $@) {
    print("Something went wrong: $e\n");
}
# BAD, DO NOT USE WITH PERLS OLDER THAN 5.14

But note that many Perl operations do not raise exceptions when they fail; they simply return an error code. This behavior can be altered via autodie for builtins and standard modules. If you're using autodie, then the standard way of doing try/catch is this (straight out of the autodie perldoc):

use feature qw(switch);

eval {
   use autodie;

   open(my $fh, '<', $some_file);

   my @records = <$fh>;

   # Do things with @records...

   close($fh);

};

given ($@) {
   when (undef)   { say "No error";                    }
   when ('open')  { say "Error from open";             }
   when (':io')   { say "Non-open, IO error.";         }
   when (':all')  { say "All other autodie errors."    }
   default        { say "Not an autodie error at all." }
}

For getting a stacktrace, look at Carp.

Solution 3

If you want something a bit more powerful than Try::Tiny, you might want to try looking at the TryCatch module in CPAN.

Solution 4

Unfortunately TryCatch has been broken with the new version 0.006020 of Devel::Declare and there seems to be no intention of fixing it. The perl core developers team also complained about the funky stuff TryCatch was relying on to make it work.

Instead there is a new implementation called Nice::Try, which is a perfect replacement.

There is no need to have semi colon on the last brace like Try::Tiny.

You can also do exception variable assignment like

  try
  {
    # something
  }
  catch( $e )
  {
    # catch this in $e
  }

It also works using class exception like

  try
  {
    # something
  }
  catch( Exception $e )
  {
    # catch this in $e
  }

And it also supports finally. Its features set make it quite unique.

Full disclosure: I have developed this module when TryCatch got broken.

Share:
84,933
pitchblack408
Author by

pitchblack408

Updated on November 11, 2021

Comments

  • pitchblack408
    pitchblack408 over 2 years

    I have found that there is the module Error that provides try and catch functionality like in java. But I am confused at how you can print the exception that returns.

    I would like to understand how to do the following

    try {
        // do something that will fail!
    
    } catch (Error e) {
        // Print out the exception that occurred
        System.out.println(e.getMessage());
    }
    

    How do I get the print of the error with the stack trace?