home ホーム search 検索 -  login ログイン  | reload edit datainfo version cmd icon diff delete  | help ヘルプ

Perl/codepiece/carp01

Perl/codepiece/carp01

Perl / codepiece / carp01
id: 115 所有者: msakamoto-sf    作成日: 2007-03-17 22:36:54
カテゴリ: Perl 

エラーメッセージを表示させるのに一番よく見かけるのが "warn" と "die" である。
それに追随して、PerlのCoreModule*1 Carp もよく使われているようである。

このモジュールは、簡潔にまとめると、「よりユーザー・開発者に分かりやすいエラーメッセージを提供する」ためのものである。サブルーチンの呼び出し履歴(バックスタックトレース)を付けてくれる、などである。

(carp, croak) と (cluck, confess) の違い

今回示すような簡単なコードピースでは違いは表面化しないのかも知れない。実際、carp(or croak)も、cluck(or confess)も、全く同じ結果になってしまった。厳密には、上記perldocで記述されているが以下のような違いがあるらしい。

  • cluck(warn相当), confess(die相当) : コールスタック内の全ての呼び出しに関する要約がついてくる。
  • carp(warn相当), croak(die相当) : より短いメッセージを出力する。(モジュールが呼び出された位置からエラーをリポートすることが可能?)

・・・よく分からないので、将来のリベンジとして残しておく。

4つの意味の違い

正直なところ、英辞郎などを引いてみても、細かいニュアンスの差になってしまい区別が付かなかった・・・。

  • carp : 難癖をつける、あら探しをする?
  • croak : 蛙がゲコゲコなく、ブツブツ不平をこぼす?
  • cluck : めんどりが鳴く、舌打ちをして不平を言う?
  • confess : 間違い・罪を認める、白状する?

コードピースと出力($SIG{__WARN__}, $SIG{__DIE__})

  • コードピース : carp01.pl (carp, croakの実験)
#!/usr/bin/perl
use strict;
use warnings;
use Carp;

# "warn"発生時のシグナルハンドラ
sub w01 {
	print "======= WARN SIGNAL HANDLER\n";
	my ($msg) = @_;
	print $msg, "\n";
}
$SIG{__WARN__} = \&w01;

# "die"発生時のシグナルハンドラ
sub d01 {
	print "======= DIE SIGNAL HANDLER\n";
	my ($msg) = @_;
	print $msg, "\n";
}
$SIG{__DIE__} = \&d01;

sub f01 { &f02(); }
sub f02 { &f03(); }
sub f03 {
	carp("OOPS!!");
	#croak("OOPS!!");
};
eval { &f01(); };
if ($@) {
	print '------- $@ is caught', "\n";
	warn $@;
}
  • 出力1 : warn相当の"carp"時
$ ./carp01.pl
======= WARN SIGNAL HANDLER
OOPS!! at ./carp01.pl line 32
        main::f03() called at ./carp01.pl line 28
        main::f02() called at ./carp01.pl line 24
        main::f01() called at ./carp01.pl line 37
        eval {...} called at ./carp01.pl line 36
  • 出力2 : die相当の"croak"時
$ ./carp01.pl
======= DIE SIGNAL HANDLER
OOPS!! at ./carp01.pl line 33
        main::f03() called at ./carp01.pl line 28
        main::f02() called at ./carp01.pl line 24
        main::f01() called at ./carp01.pl line 37
        eval {...} called at ./carp01.pl line 36

------- $@ is caught
======= WARN SIGNAL HANDLER
OOPS!! at ./carp01.pl line 33
        main::f03() called at ./carp01.pl line 28
        main::f02() called at ./carp01.pl line 24
        main::f01() called at ./carp01.pl line 37
        eval {...} called at ./carp01.pl line 36

warnとdieを処理する、特別なシグナル処理、 $SIG{__WARN__}, $SIG{__DIE__} を使用し、本当にdie相当/warn相当が処理されているのかを確認してみる。その結果 carp を用いると、確かにwarn用のシグナルハンドラが走っていることがわかる。また、croakの場合、一度die用のシグナルハンドラが走ってから(これ自体はdie相当ということで問題ない)、 $@がセットされる ため、下のwarn処理に走り、それにより今度はwarn用のシグナルハンドラが走っている。

続いて carp, croak を cluck, confessに変えてみる。コードピースは省略する。

  • 出力1 : warn相当の"cluck"時
$ ./carp01.pl
======= WARN SIGNAL HANDLER
OOPS!! at ./carp02.pl line 32
        main::f03() called at ./carp02.pl line 28
        main::f02() called at ./carp02.pl line 24
        main::f01() called at ./carp02.pl line 37
        eval {...} called at ./carp02.pl line 36
  • 出力2 : die相当の"confess"時
$ ./carp01.pl
======= DIE SIGNAL HANDLER
OOPS!! at ./carp02.pl line 33
        main::f03() called at ./carp02.pl line 28
        main::f02() called at ./carp02.pl line 24
        main::f01() called at ./carp02.pl line 37
        eval {...} called at ./carp02.pl line 36

------- $@ is caught
======= WARN SIGNAL HANDLER
OOPS!! at ./carp02.pl line 33
        main::f03() called at ./carp02.pl line 28
        main::f02() called at ./carp02.pl line 24
        main::f01() called at ./carp02.pl line 37
        eval {...} called at ./carp02.pl line 36

このように、carp/croakと出力に差異は見られなかった。 恐らく簡単なコードピースではこの差異は表に出てこないと思われる。
とはいえ、cluck/confessでも、warn相当/die相当でシグナルハンドラが処理されていることを確認できた。


*1: 少なくもPerl5.8系列ではCoreModule

プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2008-12-24 22:42:18
md5:74340f186d7d9a7eb907f8bc26573728
sha1:edc946862fe9b7d8803a4f0b29d35398c65abef1
コメント
コメントを投稿するにはログインして下さい。