Perl/codepiece/try-catch-exception01で、基本的なエラーの捕捉方法を確認した。
ここでは、より実際のシーンを意識し、以下のシチュエーションでエラーを捕捉できるか確認する。
いずれも perldiag(http://perldoc.perl.org/perldiag.html) では(F)(trappable fatal error)に分類されている。
ディレクトリ構成:
./try05/ ./try05/try05.pl : main ./try05/Hoge/ ./try05/Hoge/Bohe.pm : empty package module
#!/usr/bin/perl
use strict;
use warnings;
use File::Basename;
use Data::Dumper;
use Error qw(:try);
sub BEGIN {
my (undef, $__base_dir, undef) = fileparse($0);
push(@INC, $__base_dir);
}
# 存在しないパッケージをrequireしてみる。
try {
my $pkg_name = "Hoge::Hoge";
eval("require $pkg_name;");
if ($@) {
throw Error(-text => $@);
}
} catch Error with {
my $e = shift;
print Dumper($e), "\n";
};
# 存在しないパッケージ関数を呼んでみる。
try {
my $pkg_name = "Hoge::Bohe";
eval("require $pkg_name;");
my $obj = $pkg_name->new();
} catch Error with {
my $e = shift;
print Dumper($e), "\n";
};
package Hoge::Bohe; use strict; use warnings; 1;
$ ./try05/try05.pl
$VAR1 = bless( {
'-file' => 'try05/try05.pl',
'-text' => 'Can\'t locate Hoge/Hoge.pm in @INC (@INC contains: ... try05/) at (eval 3) line 1.
',
'-line' => 17,
'-package' => 'main'
}, 'Error' );
$VAR1 = bless( {
'-file' => 'try05/try05.pl',
'-text' => 'Can\'t locate object method "new" via package "Hoge::Bohe"',
'-line' => '27',
'-package' => 'Error'
}, 'Error::Simple' );
まず、エラー捕捉の仕方が異なる点に注目する。
最初、前者の方でもtry-catchに任せてみたが、 catchに捕捉されない 現象が発生した。試しに手動で$@チェックを入れてみたところ上手く行った。(evalの特性と関係するのかも知れない。)
逆に、後者の方で$@の手動チェックを入れても、そこは通らない。未定義関数の呼び出しの方では、即座にcatchへ入る(=dieがブロック中で発生している?)ようである。
いずれにせよ、パッケージモジュールロード時の eval("require $pkg_name") のエラーハンドリングは$@の手動チェックが欠かせないことを確認した。