Perl:没有死的捕获错误

Pma*_*oen 8 error-handling perl die

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

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

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

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

我怎么去抓这个?

我试过这样使用$SIG{__DIE__}:

local $SIG{__DIE__} = sub {
  my $e = shift;
  print "Error: " .$e;
};
Run Code Online (Sandbox Code Playgroud)

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

错误:

在它面前.

spa*_*azm 8

DBI connect(...)失败:ORA-12154:TNS:无法解析指定的连接标识符(DBD ERROR: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
    }
}
Run Code Online (Sandbox Code Playgroud)

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


Pma*_*oen 3

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

  • 没错,这是警告而不是死亡,必须先安装处理程序。如果将其包装在“BEGIN{}”中,则可以将其安装在任何模块中。 (3认同)