我使用DBI模块连接数据库.
我可以捕获我自己的死并处理它们就好了但是当我的数据库连接失败时,DBI模块显然打印出它自己的死:
DBI connect(…) Failed: ORA-12154: TNS:could not resolve the
connect identifier specified (DBD ERROR: OCIServerAttach) at …
我怎么去抓这个?
我尝试使用$SIG {__ DIE__},如下所示:
local $SIG{__DIE__} = sub { my $e = shift; print "Error: " .$e; };
这是在我的主文件的底部,在这个文件中我也调用了我自己的模块中可用的connect子例程.我也尝试将这段代码放在我的模块的底部,但它仍然打印出没有的错误
Error:
在它面前.
解决方法
DBI connect(…) Failed: ORA-12154:
TNS:could not resolve the connect
identifier specified (DBD ERROR:
OCIServerAttach) at …How would I go about catching this ?
要捕获并处理此级别的错误,请使用块形式的eval,“eval {…}”.这将捕获子代码中发生的任何骰子.如果eval块中的代码死掉,它将设置$@,并且该块将返回false.如果代码没有死,$@将被设置为”.
使用SIG {WARN}和SIG {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块设置并处理本地化$@并处理其他边缘情况.