开发者

How do you best attribute errors in a Perl method to the caller

开发者 https://www.devze.com 2023-03-13 00:21 出处:网络
Given a method that may fail with warnings and/or errors, I want the error method to show up at the caller. Fir instance this script:

Given a method that may fail with warnings and/or errors, I want the error method to show up at the caller. Fir instance this script:

foo(0);         # line 1

sub foo {
    1 / shift;  # line 4
}

Produces the error Illegal division by开发者_如何转开发 zero at foo.pl line 4, but I want Illegal division by zero at foo.pl line 1. There should be several ways if I put the method in a module or if I wrap the method body in eval, but I have not found an easy way like this:

sub foo {
    attributeErrorsToCaller; # do some magic
    1 / shift;
}

Is there such a way?


EDIT: mirod's answer comes close not what I was looking for:

Foo::foo(0);         # line 1

package Foo;
use diagnostics -traceonly;
BEGIN { disable diagnostics; }

sub foo {
    enable diagnostics;
    1 / shift;       # line 9
}

Without enable diagnostics the error message is Illegal division by zero at foo.pl line 9.. With enable diagnostics it is still too verbose, but this may also be useful:

Uncaught exception from user code:
    Illegal division by zero at foo.pl line 10.
 at foo.pl line 10
     Foo::foo(0) called at foo.pl line 2

I bet I could hack diagnostics to get exactely the feature I want, but using diagnostics as raw module is probably more recommended.


Carp is very, very close to "do_some_magic" you are asking for. For instance:

#!/usr/bin/perl -w 
use strict;

# I fork to be as close to natural die() as possible. 
fork() or Foo::foo();
fork() or Foo::bar();
fork() or Foo::baz();
sleep 1;

package Foo;
use Carp; 

sub foo { die "Some error (foo)"; }; 
sub bar { croak "Some error (bar)"; }; 
sub baz { bar(); };

As you can see, croak() acts almost like die(), but reports error to the caller (even indirectly -- see baz).

However, it won't handle 1/0 for you -- either use eval (or even Try::Tiny), or check input values* and say "division by zero" yourself.

Carp is standard, which means understandable by further maintainers of your code, and also can print neat stack traces via confess or cluck or even print Carp::longmess (see the doc).

*which is good anyway


Would use diagnostics; be enough for you? It will dump the call stack, so the caller is quite easy to find out.

For example in you example:

#!/usr/bin/perl

use strict;
use warnings;
use diagnostics;


foo(0);

sub foo
  { 
    return 1/$_[0];
  }

gives this:

`Illegal division by zero at test_die line 12 (#1)
    (F) You tried to divide a number by 0.  Either something was wrong in
    your logic, or you need to put a conditional in to guard against
    meaningless input.

Uncaught exception from user code:
        Illegal division by zero at test_die line 12.
 at test_die line 12
        main::foo(0) called at test_die line 8


Not like you describe. You can implement Debug::Trace to pull off a full back trace.

You may also find the perl caller which is quite useful for this type of debugging. But for a live application you will likely need to do more detailed tracing.

http://perldoc.perl.org/functions/caller.html

0

精彩评论

暂无评论...
验证码 换一张
取 消