Perl 简明教程
Perl - Error Handling
执行和错误总是同时发生的。如果你正在打开一个不存在的文件。那么如果你没有正确处理此情况,你的程序将被视为质量很差。
如果发生错误,程序将停止。因此,使用适当的错误处理来处理各种类型的错误,这些错误可能会在程序执行期间发生并采取适当的操作,而不是完全停止程序。
你可以用多种不同的方式识别和捕获错误。在 Perl 中捕获错误并正确处理它们非常容易。这里有一些可用的方法。
The if statement
当需要检查语句的返回值时, if statement 是显而易见的选择;例如 -
if(open(DATA, $file)) {
...
} else {
die "Error: Couldn't open the file - $!";
}
这里变量 $! 返回实际的错误消息。或者,在有意义的情况下,我们可以将语句缩减为一行;例如 -
open(DATA, $file) || die "Error: Couldn't open the file $!";
The unless Function
unless 函数与 if 相反:语句可以完全绕过成功状态,并且仅在表达式返回 false 时执行。例如 -
unless(chdir("/etc")) {
die "Error: Can't change directory - $!";
}
unless 语句最适合在仅当表达式失败时引发错误或替代项时使用。当在单行语句中使用时,该语句也有意义 -
die "Error: Can't change directory!: $!" unless(chdir("/etc"));
我们仅在 chdir 操作失败时才执行,并且它易于理解。
The ternary Operator
对于非常短的测试,可以使用条件运算符 ?:
print(exists($hash{value}) ? 'There' : 'Missing',"\n");
这里我们尝试实现的目标并不是很清楚,但效果与使用 if 或 unless 语句相同。当希望在一个表达式或语句中快速返回两个值中的一个时,条件运算符最好用。
The warn Function
warn 函数只是发出警告,消息会打印到 STDERR,但不会执行进一步的操作。因此,如果你只想为用户打印警告并继续执行其余的操作,则它会更有用 -
chdir('/etc') or warn "Can't change directory";
The die Function
die 函数的工作方式与 warn 一样,只是它还调用 exit。在正常脚本中,此函数的效果是立即终止执行。如果程序中出现错误并且继续进行毫无用处,则应使用此函数 -
chdir('/etc') or die "Can't change directory";
Errors within Modules
我们应该能够处理两种不同的情况 -
-
报告引用模块的文件名和行号的错误 - 这在调试模块时很有用,或者当你特别想引发与模块相关(而不是与脚本相关)的错误时很有用。
-
报告引用调用者信息的错误,以便调试导致错误的脚本中的行。以这种方式引发的错误对于最终用户很有用,因为它们突出显示了与调用脚本的起始行相关的错误。
当从模块中调用时, warn 和 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 模块,它提供了一种简化方法来报告模块中的错误,并返回有关调用脚本的信息。Carp 模块提供四个函数:carp、cluck、croak 和 confess。这些函数在下面讨论。
The carp Function
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
The cluck Function
cluck 函数是一种超强的 carp,它遵循相同的基本原则,但还会打印包含所有导致调用该函数的模块的堆栈跟踪,其中包括原始脚本的信息。
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
The croak Function
功能 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 函数的基本规则。
The confess Function
功能 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