perl - 如何为模具处理程序提供更多上下文?

标签 perl exception

如果某些功能必须 die,我希望在错误消息中有更多上下文.在某些情况下我可以提供它,在其他情况下我找不到好方法。例如,使用 RaiseError与 Postgres 相关的选项我在每次失败时都会遇到异常,但我无法为这些错误提供更多上下文。我尝试使用 die -handler,但我无法找到一种理智的方式来包含被调用子程序的参数,至少:

try {
  x( 'y' );
} catch {
  say "CATCHED error: $_";
};

sub _die_handler {
  my @caller = caller(1);
  say "@caller"; # how to access @_ for this frame 
  die @_;
}

sub x {
 local $SIG{__DIE__} = \&_die_handler;
 die;
}


我怎么能在上面的例子中看到 x以“y”作为参数调用?

如果我没有修改@_在我的子程序中,我可以从我的_die_handler 访问它吗? ?或者我可以事先向处理程序提供一些数据吗?

我现在看到的两个选项:
  • 通过一些全局变量,我总是预先填充所需的数据,以防出现错误
  • 使用对象,其中包含 die_handler-method

  • 更好的方法来做到这一点?

    最佳答案

    我不确定你想要什么“上下文”,但是 Carp是我们这里的 friend 。

    一方面,包括 use Carp::Always;我们会在所有错误上打印完整的堆栈回溯。

    如果您更愿意选择,最简单的方法是直接使用合适的Carp常规

    use warnings;
    use strict;
    use feature 'say';
    
    use Carp;
    
    eval { my $y = 10;  x($y) };
    if ($@) {
        print "eval: $@";
        # print/log else as wanted, recover and proceed or exit
    }
    
    say "done";
    
    sub x {
        local $SIG{__DIE__} = \&Carp::confess;
        # ...
        my $bad_math = $_[0] / 0;
    }
    
    Carp::confess死了,具有完整的堆栈回溯,但在您的示例中 dieeval 捕获.死于confess并捕获异常,您会从 confess 获得“调用上下文”但也可以在 eval 中保留控制权以按照您的意愿继续进行。 “捕获。”

    这打印
    eval: Illegal division by zero at error_context.pl line 18.
     at error_context.pl line 18.
            main::x(10) called at error_context.pl line 7
            eval {...} called at error_context.pl line 7
    done
    

    Without eval the program would terminate (unless there's an eval further up the stack) but we'd still get the full backtrace of the call. There are routines in Carp which don't die, and among them cluck also prints backtrace.

    For a more custom handling use the $SIG{__DIE__} hook. A little snag with Carp is that the routine with backtrace which doesn't die, cluck, just prints to STDERR stream; we can't easily get that message to build it up further. The trace used to be in longmess but is not anymore and I don't think that one can get the stacktrace from Carp without die-ing.

    Then use confess, which returns the trace, and wrap the call with eval

    sub _die_handler {
        my $other_info = '...';
        Carp::confess($other_info . "\n" . $_[0]);
    }
    ...
    sub x { 
        local $SIG{__DIE__} = \&_die_handler;
        ...
    }
    ...
    eval { x() };
    if ($@) { ... }  #-->  confess's trace with $other_info prepended 
    

    所以当你处理它的die整个消息然后在$@在您的 eval .为此,您仍然需要 eval .

    如果您希望能够在钩子(Hook)中完全处理异常,请参阅 Devel::StackTrace
    use Devel::StackTrace;
    
    sub _die_handler {
        my $trace = Devel::StackTrace->new;
        # Add other info to `$trace` object, or build error object/structure 
        # Print/log/etc  $trace (or your new error structure/object), or
        #die $trace;
    }
    
    Devel::StackTrace如果你想重新抛出当然也很有用,在这种情况下你可以将它的对象传递给 die .请参阅文档,特别是构造函数选项。

    一般警告:小心 $SIG{__DIE__} ;这可能很棘手。我想说,最好使用 Carp .

    最后,如果“上下文”是指调用堆栈中的更多详细信息,则可以使用 caller 手动遍历堆栈。并通过 PadWalker 从每一帧中检索词汇. this post 中的一个示例.

    关于perl - 如何为模具处理程序提供更多上下文?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58906167/

    相关文章:

    perl - 使用Perl搜索并替换文件中的特定字符串

    perl - 将字符串(用户名)映射到 Perl 中的 UUID

    Java Picasa API 目录列表不起作用

    Swift 3 - CollectionView 选择不可见

    perl - PDB 文件中一点到所有其他点之间的距离

    c - 将数据从 c 发送到 perl

    java - Intellij IDEA插件无法运行

    java - 从 Weka Java API 获取欧几里得距离

    java - 当可以读取文件但文件数据格式不正确时,Java 中应该使用什么异常?

    regex - 如何在匹配模式后插入字符串