我正在学习Perl,在很多示例中,错误的处理方式是这样的:
open FILE, "file.txt" or die $!;
在脚本中使用 die
来处理错误真的是最好的方式吗?
我正在学习Perl,在很多示例中,错误的处理方式是这样的:
open FILE, "file.txt" or die $!;
在脚本中使用 die
来处理错误真的是最好的方式吗?
在脚本中间使用die
是否合适,这取决于你正在做什么。如果只是几十行代码,那么使用它也没问题。对于有几百行代码的小工具,可以考虑使用 confess (请参见下文)。如果是一个大型面向对象系统,包含许多类和相互连接的代码,则异常对象可能更好。
Carp 包中的 confess:
通常导致程序崩溃的 bug 不一定在报告 die 的那一行。
将 die 替换为 confess(请参见 Carp 包)将提供堆栈跟踪信息(我们如何到达此行),这极大地有助于调试。
对于处理 Perl 内置函数抛出的异常,我喜欢使用autodie。它捕获了 open
和其他系统调用的失败,并会为您抛出异常,无需编写 or die
。这些异常可以使用 eval { }
捕获,或者更好的方式是使用Try::Tiny。
autoOrDie
:) - friedoauthorDie
了 :) - dolmen由于我在几乎所有地方都使用 Log::Log4perl,所以我使用 $logger->logdie
代替 die
。如果你想更好地控制你的异常,请考虑使用 Exception::Class。
最好使用Try::Tiny来捕获异常(请查看其文档以了解原因)。
无法打开文件并给出文件名而死亡要比系统告诉你无法从未定义的匿名文件中读取或写入更好。
如果你谈论一个“脚本”,通常情况下你谈论的是一段相当简单的代码。不需要协调层次(通常不需要)。在 Perl 模块中,伴随着的观念是你不拥有执行环境,所以主要软件关心并在 eval 中捕获异常,或者根本不关心,死亡也是可以接受的。然而,你应该尝试让模块更加健壮,只需传回 undefs 或其他内容即可。
你可以在 eval 块中捕获所有死亡(或 croaks),并在此处理更具体的问题。
但如果你想检查 $!,那么编写该代码,你会得到更具体的解决方案。
看看使用 strict
的几乎普遍标准。这是在可疑语法上死亡的代码,而不是让你继续进行。
所以我认为一般的想法是:是的,死亡,除非你有更好的处理方法。如果你有足够的远见,可以因为你知道不需要死亡而被原谅一两次。
use Carp;
my $fh;
open $fh, '<', "file.txt" or confess($!);
我使用die,但将其包装在eval块中以控制错误处理:
my $status = eval
{
# Some code...
};
如果 'eval' 失败:
$status
将未定义。$@
将被设置为产生的任何错误消息(或 die
的内容)如果 'eval' 成功:
$status
将是块的最后一个返回值。$@
将被设置为 ''。eval {}
存在许多问题,需要使用晦涩的解决方法...如果你关心错误的识别。如果你无论出现什么原因都会采取相同的行动,那么一个简单的块级 eval
就可以了。但是,在所有其他情况下,请使用 Try::Tiny
。 - Dave Sherohman正如@friedo所写,如果这是一个独立的几行脚本,die是可以的,但我认为在模块或require'd代码片段中使用die不是一个好主意,因为它会打断程序的流程。我认为流程控制应该是程序主体的特权。
因此,在模块中,我认为最好返回undef,例如return
,它将在标量上下文中返回undef,在列表上下文中返回空列表,并设置一个异常对象以供获取更多详细信息。这个概念在模块Module::Generic中实现如下:
# in some module
sub myfunc
{
my $self = shift( @_ );
# some code...
do{ # something } or return( $self->error( "Oops, something went wrong." ) );
}
然后,在调用者中,您将写入:
$obj->myfunc || die( "An error occurred at line ", $obj->error->line, " with stack trace: ", $obj->error->trace );
这里error
将设置一个异常对象并返回undef。
然而,因为许多模块使用die
或croak
,您还需要使用eval或try-catch块(例如Nice::Try)来捕获这些中断。
完全披露:我是Module::Generic和Nice::Try的开发人员。