Perl:没有死的捕获错误

时间:2010-04-13 09:41:24

标签: perl error-handling die

我正在玩错误处理并遇到一些问题。 我使用DBI模块连接数据库。

我通过使用我调用错误的子例程来进行自己的错误处理。

我可以抓住我自己的死并处理它们就好了但是当我的数据库连接失败时,DBI模块显然打印出它自己的模具:

  

DBI连接(...)失败:ORA-12154:TNS:无法解析       指定连接标识符(DBD ERROR:OCIServerAttach)在...

我该如何抓住这个?

我尝试使用$SIG{__DIE__},如此:

local $SIG{__DIE__} = sub {
  my $e = shift;
  print "Error: " .$e;
};

这是在我的主文件的底部,在这个文件中我也调用了我自己的模块中可用的connect子例程。我也尝试将这段代码放在我的模块的底部,但它仍然打印出没有

的错误
  

错误:

在它面前。

5 个答案:

答案 0 :(得分:8)

  

DBI连接(...)失败:ORA-12154:   TNS:无法解决连接问题   指定的标识符(DBD错误:   OCIServerAttach)在......

     

我该如何抓住这个?

要捕获并处理此级别的错误,请使用块形式的eval,“eval {...}”。这将捕获子代码中发生的任何骰子。如果eval块中的代码死掉,它将设置$ @并且该块将返回false。如果代码没有死,$ @将被设置为''。

通过SIG {WARN}和SIG {DIE}使用信号处理很麻烦,因为它们是全局的,还有一些竞争条件需要考虑(如果我在处理不同的信号时收到信号会怎么样?等等。传统的基于信号的计算问题)。您可能正在编写单线程代码,因此您不必担心调用die的多个事件的并发问题,但是有用户需要考虑(也许他会在您尝试打开DBI连接时发送SIGKILL )

在这种特定情况下,您使用的是DBI。使用DBI,您可以控制出现错误的情况,如果它应该死,警告或静默失败,并等待您检查返回状态。

以下是使用eval {...}的基本示例。

my $dbh = eval { DBI->connect( @args) };
if ( $@ )
{
    #DBI->connect threw an error via die
    if ($@ =~ m/ORA-12154/i )
    {
        #handle this error, so I can clean up and continue
    }
    elsif ( $@ =~ m/SOME \s* other \s* ERROR \s+ string/ix )
    {
       #I can't handle this error, but I can translate it
        die "our internal error code #7";
    }
    else 
    {
      die $@; #re-throw the die
    }
}

以这种方式使用eval存在一些小问题,与$ @的全局范围有关。 Try::Tiny cpan页面有很好的解释。 Try :: Tiny处理最小的Try / catch块设置并处理本地化$ @并处理其他边缘情况。

答案 1 :(得分:3)

好的,找到了解决方案,显然我需要__WARN__而不是__DIE__,这段代码需要位于文件的顶部,在抛出错误之前,与示例I不同阅读说明:)

答案 2 :(得分:3)

SIG{__DIE__}区块中包含此内容:

### Check if exceptions being caught.
return if $^S;

这将阻止您的处理程序用于在eval块中生成die的基于异常的代码。

答案 3 :(得分:2)

DBI中有很多开关,比如PrintError,RaiseError等,你可以调整它们。 见http://search.cpan.org/perldoc?DBI

答案 4 :(得分:0)

这不像一个整体模具捕获器那样通用,但是专门针对DBI错误处理我们实际上有自己的模块提供数据库调用的包装器;并且模块的一个功能是围绕每个DBI调用包装eval(取决于标志)。

这允许我们在数据访问级别上执行自定义错误处理,例如查询重试,统计信息,自动故障转移等等 - 所有这些都对代码的其余部分都是透明的。