Perl中错误处理的最佳实践是什么?

时间:2010-05-19 20:49:44

标签: perl error-handling

我正在学习Perl,在很多例子中,我看到错误就像这样处理

open FILE, "file.txt" or die $!;

脚本中间的die真的是处理错误的最佳方法吗?

6 个答案:

答案 0 :(得分:21)

脚本中间的die是否合适取决于你正在做什么。如果它只有几十行,那就没关系了。一个有几百行的小工具,然后考虑忏悔(见下文)。如果它是一个包含大量类和互连代码的大型面向对象系统,那么异常对象可能会更好。

承认Carp包裹:
通常导致死亡的错误不在报告的线上。 用confess替换die(参见Carp包)将给出堆栈跟踪(我们如何到达这一行),这极大地有助于调试。

为了处理来自Perl builtins的异常,我喜欢使用autodie。它从open和其他系统调用中捕获失败,并为您抛出异常,而不必执行or die位。使用Try::Tiny可以使用eval { }或更好的方式捕获这些例外情况。

答案 1 :(得分:13)

由于我几乎在所有地方使用Log::Log4perl,因此我使用$logger->logdie代替die。如果您想要更好地控制例外,请考虑Exception::Class

最好使用Try::Tiny捕获您的例外情况(请参阅其文档原因)。

答案 2 :(得分:7)

除非你有更具体的想法,否则你想在意想不到的事情发生时死去。

  • 因未能打开文件并提供文件名而死亡的情况要好于系统告诉您它无法读取或写入匿名的未定义文件。

  • 如果您正在谈论“脚本”,通常您会谈论一段非常简单的代码。不是需要协调的层(通常不是)。在Perl 模块中,有一个附带的想法是你不拥有执行环境,因此主要软件关心并且它在eval中捕获事物,或者它并不真正关心和死了会好的。但是,你应该尝试将一个更强大的功能作为一个模块,然后传回undefs或其他东西。

  • 你可以捕捉到eval块中的任何骰子(或呱呱叫)。你可以在那里进行更具体的处理。

  • 但如果你想检查$!然后编写该代码,您将获得更具体的解决方案。

  • 看一下使用strict的近乎普遍的标准。那段代码死于可疑的语法,而不是让你继续。

所以我认为一般的想法是:是, DIE 除非您更好地了解应该如何处理事情。如果你有足够的远见,你可以原谅你不死的一两次,因为你知道你不需要。

答案 3 :(得分:3)

更现代的方法是使用鲤鱼标准库。

use Carp;
my $fh;
open $fh, '<', "file.txt" or confess($!);

主要优点是它可以在死亡时提供堆栈跟踪。

答案 4 :(得分:0)

我使用die但是我将它包装在eval块中以控制错误处理:

my $status = eval
{
    # Some code...
};

如果'eval'失败:

  1. $status将是未定义的。
  2. $@将设置为生成的任何错误消息(或者内容) 一个die
  3. 如果'eval'成功:

    1. $status将是该块的最后返回值。
    2. $@将设置为''。

答案 5 :(得分:0)

正如@friedo所写,如果这是一个只有几行的独立脚本,则die可以,但是我认为在模块中使用die或需要一段代码不是一个好主意,因为它会中断程序。我认为对流程的控制应该是程序主要部分的特权。

因此,我认为,最好在模块中返回undef,例如return,它将在标量上下文中返回undef,在列表上下文中返回空列表,并设置要获取的Exception对象以获取更多详细信息。像这样在模块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。

但是,由于许多模块diecroak,您还需要使用eval或try-catch块(例如Nice::Try

)来捕获这些中断。

完全公开:我是Module :: Generic和Nice :: Try的开发者。