错误处理(Error Handling)
执行和错误总是在一起。 如果要打开不存在的文件。 然后,如果你没有正确处理这种情况,那么你的程序被认为质量很差。
如果发生错误,程序将停止。 因此,使用适当的错误处理来处理各种类型的错误,这些错误可能在程序执行期间发生并采取适当的操作而不是完全停止程序。
您可以通过多种不同方式识别和捕获错误。 很容易在Perl中捕获错误然后正确处理它们。 这里有几种可以使用的方法。
if 语句
当您需要检查语句的返回值时, if statement是显而易见的选择; 例如 -
if(open(DATA, $file)) {
...
} else {
die "Error: Couldn't open the file - $!";
}
这里变量$! 返回实际的错误消息。 或者,我们可以在有意义的情况下将陈述减少到一行; 例如 -
open(DATA, $file) || die "Error: Couldn't open the file $!";
除非功能
unless函数与if:逻辑相反,语句可以完全绕过成功状态,只有在表达式返回false时才执行。 例如 -
unless(chdir("/etc")) {
die "Error: Can't change directory - $!";
}
当您只想在表达式失败时引发错误或替代时,最好使用unless语句。 在单行语句中使用时,该语句也很有意义 -
die "Error: Can't change directory!: $!" unless(chdir("/etc"));
在这里,我们只有在chdir操作失败时才会死掉,并且读得很好。
三元运算符
对于非常短的测试,您可以使用条件运算符?:
print(exists($hash{value}) ? 'There' : 'Missing',"\n");
这里不太清楚我们想要实现什么,但效果与使用if或unless语句相同。 当您想要快速返回表达式或语句中的两个值之一时,最好使用条件运算符。
警告功能
warn函数只会发出警告,会向STDERR打印一条消息,但不会采取进一步操作。 因此,如果您只想为用户打印警告并继续执行其余操作,则更有用 -
chdir('/etc') or warn "Can't change directory";
模具功能
die函数就像warn一样工作,除了它还调用exit。 在普通脚本中,此函数具有立即终止执行的效果。 如果程序中存在错误,则应该使用此函数以防止继续操作 -
chdir('/etc') or die "Can't change directory";
模块中的错误
我们应该能够处理两种不同的情况 -
报告引用模块文件名和行号的模块中的错误 - 这在调试模块时很有用,或者当您特别想要引发与模块相关但不与脚本相关的错误时。
在模块中报告引用调用方信息的错误,以便您可以在脚本中调试导致错误的行。 以这种方式引发的错误对最终用户很有用,因为它们突出显示与调用脚本的原始行相关的错误。
warn和die函数的工作方式与die调用时的工作方式略有不同。 例如,简单的模块 -
package T;
require Exporter;
@ISA = qw/Exporter/;
@EXPORT = qw/function/;
use Carp;
sub function {
warn "Error in module!";
}
1;
从下面的脚本调用时 -
use T;
function();
它会产生以下结果 -
Error in module! at T.pm line 9.
这或多或少是您所期望的,但不一定是您想要的。 从模块程序员的角度来看,信息很有用,因为它有助于指出模块本身的错误。 对于最终用户来说,所提供的信息是相当无用的,对于除了强化程序员之外的所有人来说,它完全没有意义。
这些问题的解决方案是Carp模块,它提供了一种简单的方法,用于报告模块中的错误,这些模块返回有关调用脚本的信息。 鲤鱼模块提供四种功能:鲤鱼,咯咯,croak和confess。 这些功能将在下面讨论。
鲤鱼功能
carp函数是warn的基本等价物,它将消息打印到STDERR而不实际退出脚本并打印脚本名称。
package T;
require Exporter;
@ISA = qw/Exporter/;
@EXPORT = qw/function/;
use Carp;
sub function {
carp "Error in module!";
}
1;
从下面的脚本调用时 -
use T;
function();
它会产生以下结果 -
Error in module! at test.pl line 4
咯咯的功能
cluck函数是一种增压的鲤鱼,它遵循相同的基本原则,但也打印导致被调用函数的所有模块的堆栈跟踪,包括原始脚本的信息。
package T;
require Exporter;
@ISA = qw/Exporter/;
@EXPORT = qw/function/;
use Carp qw(cluck);
sub function {
cluck "Error in module!";
}
1;
从下面的脚本调用时 -
use T;
function();
它会产生以下结果 -
Error in module! at T.pm line 9
T::function() called at test.pl line 4
croak作用
croak函数等同于die ,除了它将调用者报告一级。 与die一样,此函数在向STDERR报告错误后也会退出脚本 -
package T;
require Exporter;
@ISA = qw/Exporter/;
@EXPORT = qw/function/;
use Carp;
sub function {
croak "Error in module!";
}
1;
从下面的脚本调用时 -
use T;
function();
它会产生以下结果 -
Error in module! at test.pl line 4
与carp一样,对于根据warn和die函数包含行和文件信息,也适用相同的基本规则。
confess功能
confess功能就像cluck ; 它调用die然后打印堆栈跟踪一直到原始脚本。
package T;
require Exporter;
@ISA = qw/Exporter/;
@EXPORT = qw/function/;
use Carp;
sub function {
confess "Error in module!";
}
1;
从下面的脚本调用时 -
use T;
function();
它会产生以下结果 -
Error in module! at T.pm line 9
T::function() called at test.pl line 4