如何在Perl中捕获并重新显示错误?
假设我有一个模块栏,它是模块Foo的子类包装器。我希望调用Bar的方法来完全模仿Foo的方法,甚至是致命的错误。到目前为止,很容易;我只是调用超级方法如何在Perl中捕获并重新显示错误?,perl,Perl,假设我有一个模块栏,它是模块Foo的子类包装器。我希望调用Bar的方法来完全模仿Foo的方法,甚至是致命的错误。到目前为止,很容易;我只是调用超级方法 sub stuff { # Do stuff here SUPER::stuff(@_); # Do more stuff here } 但是,假设我想捕获、记录并重新显示任何致命错误SUPER::stuff()产生的错误。前两个步骤很简单: sub stuff { # Do stuff here
sub stuff {
# Do stuff here
SUPER::stuff(@_);
# Do more stuff here
}
但是,假设我想捕获、记录并重新显示任何致命错误SUPER::stuff()
产生的错误。前两个步骤很简单:
sub stuff {
# Do stuff here
eval {
SUPER::stuff(@_);
};
$@ and log("Naughty, naughty: $@");
# Do more stuff here
}
。。。但我不知道最后一部分怎么做。如何以调用方无法区分调用
Foo->stuff()
和调用Bar->stuff()
的方式重新抛出错误?我可以在log语句后插入die$@
并期望它做我想做的事情吗?或者这里有可能让我陷入麻烦的细微差别吗?你的建议会奏效。Perl没有结构化异常,因此调用程序无论如何只能得到$@
中的数据 在Perl中安全评估/catch/log/rethrow的完整代码可能有点冗长
eval {
SUPER::stuff(@_);
};
$@ and ( log("Naughty, naughty: $@"), die $@ );
sub stuff {
# Do stuff here
local $@; # don't reset $@ for our caller.
my $eval_ok = eval { # get the return from eval, it will be undef if the eval catches an error.
SUPER::stuff(@_);
1; # return 1 (true) if there are no errors caught.
};
if (!$eval_ok) { # don't trust $@ it might have been reset as the eval unrolled.
my $error = $@ || 'unknown error'; # copy $@ incase write_log resets $@, or is later changed to cause it to reset $@.
write_log("Naughty, naughty: $error");
die $error; # after all that we can rethrow our error.
}
# Do more stuff here
}
您可以使用sugested by mob来简化:
sub stuff {
# Do stuff here
try {
SUPER::stuff(@_);
} catch {
my $error = $_;
write_log("Naughty, naughty: $error");
die $error;
}
# Do more stuff here
}
避免在
eval
之后使用检查$@
,尤其是在OO代码中。看到@tchrist,我同意,但我也看到$@
在生产代码中出现eval
错误后被重置。@Ven'Tatsu:你觉得$
的5.14修复程序解决了这个问题吗?@tchrist,看起来会的。@Ven'Tatsu:我很高兴听到这个消息。我更愿意解决问题,而不是永远解决问题。例如,调用log
,然后调用die
,由于$
的全局性质,您不能相信log
在传递到die
之前不会更改或重置$
中的值。但是$
可以保存对象,这会给你结构化的异常。@tchrist:但是如果我只是以$@
作为我的参数,我会丢失任何数据吗?(假设我将$@
存储到另一个变量,这样它就不会被其他变量覆盖,等等)