使用 Try::Tiny 和 Module::Runtime 使用 try-catch 时避免在 Perl 中出现警告
avoiding warnings in Perl when using try-catch using Try::Tiny and Module::Runtime
我的 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 action\n";
#warn $_;
};
但不幸的是,脚本的输出在输出中间显示了这 3 个错误(所有以 Exiting subroutine 开头的行):
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
即使脚本完美运行,我发现它 "dirty" 在标准输出上显示这些错误。
有没有办法摆脱它们?
(我不能使用 if/then 等。因为我不希望脚本随着这个 require_module 退出)。
我只希望我的脚本在找不到模块时显示警报(确实如此),而不是这些警告
再次感谢
问候
在 perldoc perldiag
中,我们发现这些警告位于名为 "exiting".
的组中
如果您在 fftgv2.pl 中的第 130 行之前使用了 no warnings "exiting";
,您将关闭该块剩余部分的警告。
...当然注意警告也不是最坏的主意。
发出警告是因为您在 try
语句块内有一个 last
。 try
实际上不是 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. |
Exiting subroutine via last at ./bin/fftgv2.pl line 130.
所以第三个警告实际上是来自您 try
的子程序。
try { # here
no strict 'refs';
Exiting eval via last at ./bin/fftgv2.pl line 130.
下一个是因为Try::Tiny implements try
via a call to eval
, Perl's built-in way of catching errors.
这是 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
};
Exiting subroutine via last at ./bin/fftgv2.pl line 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 action\n";
};
last ACTION if $break_out; # oops, something went wrong, break out
}
我的 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 action\n";
#warn $_;
};
但不幸的是,脚本的输出在输出中间显示了这 3 个错误(所有以 Exiting subroutine 开头的行):
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
即使脚本完美运行,我发现它 "dirty" 在标准输出上显示这些错误。
有没有办法摆脱它们? (我不能使用 if/then 等。因为我不希望脚本随着这个 require_module 退出)。 我只希望我的脚本在找不到模块时显示警报(确实如此),而不是这些警告
再次感谢 问候
在 perldoc perldiag
中,我们发现这些警告位于名为 "exiting".
如果您在 fftgv2.pl 中的第 130 行之前使用了 no warnings "exiting";
,您将关闭该块剩余部分的警告。
...当然注意警告也不是最坏的主意。
发出警告是因为您在 try
语句块内有一个 last
。 try
实际上不是 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. |
Exiting subroutine via last at ./bin/fftgv2.pl line 130.
所以第三个警告实际上是来自您 try
的子程序。
try { # here
no strict 'refs';
Exiting eval via last at ./bin/fftgv2.pl line 130.
下一个是因为Try::Tiny implements try
via a call to eval
, Perl's built-in way of catching errors.
这是 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 };
Exiting subroutine via last at ./bin/fftgv2.pl line 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 action\n";
};
last ACTION if $break_out; # oops, something went wrong, break out
}