Net::Twitter本家のPodに書かれている例外チェックを使って上手くチェックできずにはまっていたので。本家のpodに書かれている例外チェックの基本はモジュールで用意されている関数を呼ぶ場合はevalで囲んでevalの外で$@をチェック。いちいちevalするのめんどくさいんじゃということで、下のような感じにしていた。
my $statuses = $nt->friends_timeline(); # this might die! if ( $@ ) { # friends_timeline encountered an error if ( blessed $@ && $@->isa('Net::Twitter::Error') ) { #... use the thrown error obj warn $@->error; } else { # something bad happened! die $@; } }
まぁ当然ながらこれだと、evalしてないので、evalのエラーメッセージを格納する特殊変数$@をチェックしてもしょうがない(多分)。friend_timelineの中でdieした場合にはスクリプト自体が終了する。ということで、正しくevalしませう。
eval { my $statuses = $nt->friends_timeline(); # this might die! }; if ( $@ ) { # friends_timeline encountered an error if ( blessed $@ && $@->isa('Net::Twitter::Error') ) { #... use the thrown error obj warn $@->error; } else { # something bad happened! die $@; } }
例えば、friends_timeline以前にeval内でdieが呼ばれる可能性がある場合、$@はどのような形かわからない。つまり、blessされいるか、Net::Twitter::Errorのblessか、という2点のチェックでは不十分な場合がある。そこで、$@のチェックにリファレンスかどうかのチェックを追加する。
use Scalar::Util qw/blessed/; eval { open my $fp, "<hoge.txt" or die "$!"; close $fp; my $statuses = $nt->friends_timeline(); # this might die! }; if ( $@ ) { # friends_timeline encountered an error if ( !ref $obj || blessed $@ && $@->isa('Net::Twitter::Error') ) { #... use the thrown error obj warn $@->error; } else { # something bad happened! die $@; } }
本当ならdieする可能性があるならそのつど例外ハンドリングしたほうがいいかも。あと、evalって子プロセスを走らせるんだっけ?誰か教えてくれ。