在某些功能必须执行的情况下,我想在错误消息中包含更多上下文die。在某些情况下,我可以提供它,而在另一些情况下,我找不到好的方法。例如,使用RaiseError连接Postgres 的选项,每次失败都会得到异常,但是我无法为这些错误提供更多的上下文信息。我尝试使用die-handler,但是我无法找出一种合理的方法来至少包括被称为subroutine的参数:
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;
}
Run Code Online (Sandbox Code Playgroud)
我如何在上面的示例中看到x以“ y”作为参数调用的示例?
如果我尚未@_在子程序中进行修改,可以从我的子程序中访问它_die_handler吗?还是可以事先向处理程序提供一些数据?
我现在看到两个选择:
更好的方法呢?
我不确定您想要什么“上下文”,但是Carp是我们的朋友。
首先,通过包括在内,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;
}
Run Code Online (Sandbox Code Playgroud)
该Carp::confess模具,一个完整的堆栈跟踪,但在你的例子die是由抓eval。通过消除confess异常并捕获异常,您可以从中获得“调用上下文”,confess但也可以保留控制权,以按照您希望的方式在eval“捕获”中进行操作。
此打印
eval:在error_context.pl第18行被非法除以零。
在error_context.pl第18行。
main :: x(10)在error_context.pl第7行调用
eval {...}在error_context.pl第7行调用
做完了
没有eval该程序将终止(除非eval堆栈进一步扩展),但我们仍将获得调用的完整回溯。有些例程Carp不会死,并且其中cluck还显示回溯。
要进行更多自定义处理,请使用$SIG{__DIE__}钩子。有一点麻烦的Carp是,带有回溯跟踪的例程不会死掉cluck,只是打印到STDERR流中;我们无法轻易获得该消息以进一步构建它。跟踪曾经在,longmess但现在已经不在了,我不认为Carp没有die-ing 就可以从中获取堆栈跟踪。
然后使用confess,返回跟踪,并使用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
Run Code Online (Sandbox Code Playgroud)
因此,当您处理它时die,整个消息就会出现$@在您的eval。为了这个工作,您仍然需要eval。
如果您希望能够完全处理异常,请参阅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;
}
Run Code Online (Sandbox Code Playgroud)
的 Devel::StackTrace,如果你想再次引发,在这种情况下,你可以通过它的对象当然是有用的也是die。请参阅文档,尤其是构造函数选项。
一般警告:小心$SIG{__DIE__};这可能很棘手。我会说,最好使用Carp。
最后,如果“ 上下文 ”是指调用堆栈中的更多细节,则可以使用手动遍历堆栈,caller并通过检索每个帧中的词法PadWalker。这篇文章中的一个例子。
| 归档时间: |
|
| 查看次数: |
59 次 |
| 最近记录: |