避免在 Perl 中使用 try::Tiny 和 Module::Runtime 时使用 try-catch 时出现警告



我目前在我的perl脚本的一部分中有这段代码(工作正常):

try {
no strict 'refs';
require_module $modules{$action_name};
if ( &{"FFTG::${actiontype}::run"}( $action, $fs, $log ) ) {
$log->res("SUCCESS");
} else {
if ( $action->{mandatory}[0] == 1 ) {
$log->res("FAIL, exiting.");
last ACTION;
} else {
$log->res("FAIL, but not mandatory, continuing..");
}
}
}
catch {
$log->res("MODULE NOT FOUND");
print "no module found for action '$actiontype', unable to process this actionn";
#warn $_;
};

但不幸的是,脚本的输出在输出中间显示以下 3 个错误(所有行都以Exiting 子例程开头):

starting transfer ..
no module found for action 'Transfer', unable to process this action
no module found for action 'Transfer', unable to process this action
no module found for action 'Archive', unable to process this action
Exiting subroutine via last at ./bin/fftgv2.pl line 130.
Exiting eval via last at ./bin/fftgv2.pl line 130.
Exiting subroutine via last at ./bin/fftgv2.pl line 130.
ending transfer

即使脚本运行良好,我也发现在标准输出上显示这些错误是"肮脏的"。

有没有办法摆脱它们? (我不能使用 if/then 等,因为我不希望脚本以这个require_module的事情退出)。 我只希望我的脚本在找不到模块时显示警报(它确实如此),而不是这些警告

再次感谢 问候

perldoc perldiag中,我们发现这些警告位于名为"exiting"的组中。

如果您在 fftgv2.pl 第 130 行之前使用了no warnings "exiting";,则会使该块其余部分的警告静音。

。当然,注意警告也不是最糟糕的主意。

发出警告是因为您在try语句的块内有一个lasttry实际上并不是 Perl 语法的一部分。它不是一个关键字,因此,块并不是一个真正的块。它只是一个匿名的子,由于 Try::Tiny 中的原型sub try (&;@)而被视为一个块。

我们将从下往上看它。

Exiting subroutine via last at ./bin/fftgv2.pl line 130. ^
Exiting eval via last at ./bin/fftgv2.pl line 130.       |
Exiting subroutine via last at ./bin/fftgv2.pl line 130. |

通过 ./bin/fftgv2.pl第 130 行的最后一个退出子例程。

所以第三个警告实际上是来自你try的潜艇.

try {                      # here
no strict 'refs';

通过 ./bin/fftgv2.pl第 130 行的最后一个退出 eval。

下一个是因为 Try::Tiny 通过调用eval来实现try,这是 Perl 捕获错误的内置方式。

这是代码 Try::Tiny 用途(突出显示我的评论):

# failed will be true if the eval dies, because 1 will not be returned
# from the eval body
my $failed = not eval {              # here is 2)
$@ = $prev_error;

# evaluate the try block in the correct context
if ( $wantarray ) {
@ret = $try->();                 # and this is 3)
} elsif ( defined $wantarray ) {
$ret[0] = $try->();
} else {
$try->();
};

return 1; # properly set $failed to false
};

通过 ./bin/fftgv2.pl第 130 行的最后一个退出子例程。

第一个警告来自 Try::Tiny 本身的实际sub try


那你能做些什么呢?如果您不想只是隐藏警告,则需要稍微重写代码。摆脱try块内部的last,而是通过die退出,或者干脆return。请记住,它毕竟是一个函数。

然后设置一个值,稍后使用该值来决定是否要跳过迭代。

ACTION: foreach my $action_name (@foo) {
my $break_out;
try {
no strict 'refs';
require_module $modules{$action_name};
if ( &{"FFTG::${actiontype}::run"}( $action, $fs, $log ) ) {
$log->res("SUCCESS");
}
else {
if ( $action->{mandatory}[0] == 1 ) {
$log->res("FAIL, exiting.");
return $break_out = 1; # use this to exit the loop later
}
else {
$log->res("FAIL, but not mandatory, continuing..");
}
# return is only needed if there is more code here ...
}
# ... or here
}
catch {
$log->res("MODULE NOT FOUND");
print "no module found for action '$actiontype', unable to process this actionn";
};
last ACTION if $break_out; # oops, something went wrong, break out
}

最新更新