9

エラー処理で遊んでいて、少し問題が発生しました。DBIモジュールを使用してデータベースに接続します。

エラー時に呼び出すサブルーチンを使用して、独自のエラー処理を行います。

自分のダイをキャッチして問題なく処理できますが、データベース接続に失敗すると、DBIモジュールは明らかに自分のダイを出力します。

DBI connect(...)が失敗しました:ORA-12154:TNS:指定された接続識別子(DBDエラー:OCIServerAttach)を解決できませんでした...

これをどうやって捕まえるの?

$SIG{__DIE__}私はそのように使ってみました:

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

これは私のメインファイルの一番下にあります。このファイルでは、自分のモジュールで使用できる接続サブルーチンも呼び出します。また、このコードをモジュールの下部に配置しようとしましたが、それでもエラーが出力されます。

エラー:

その前に。

4

5 に答える 5

9

DBI connect(...)が失敗しました: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 :: Tinycpanページにはすばらしい説明があります。Try :: Tinyは、最小限のTry / catchブロック設定を処理し、$@のローカライズとその他のエッジケースの処理を処理します。

于 2010-04-14T07:11:28.713 に答える
3

これをSIG{__DIE__}ブロックに含めます。

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

これにより、evalブロック内でダイを生成する例外ベースのコードでハンドラーが使用されるのを防ぐことができます。

于 2010-04-14T13:30:04.803 に答える
3

さて、解決策を見つけました。明らかに私が__WARN__代わりに必要__DIE__であり、私が読んだ例とは異なり、エラーがスローされる前に、このコードをファイルの先頭に置く必要がありました:)

于 2010-04-13T11:27:24.267 に答える
2

DBIには、PrintError、RaiseErrorなど、調整可能なスイッチがたくさんあります。http://search.cpan.org/perldoc?DBIを参照してください

于 2010-04-13T11:03:27.973 に答える
0

これは全体的なダイキャッチャーほど一般的ではありませんが、特にDBIエラー処理のために、データベース呼び出しのラッパーを提供する独自のモジュールが実際にあります。モジュールの機能の1つは、eval各DBI呼び出しを(フラグに応じて)ラップすることです。

これにより、クエリの再試行、統計、自動フェイルオーバーなど、データアクセスレベルでカスタムエラー処理を実行できます。これらはすべて、残りのコードに対して透過的です。

于 2010-04-13T13:47:58.967 に答える