Perlスクリプトの現在の位置に先行するサブコールの任意の深さまでのサブ+モジュールのリストに(印刷用に)アクセスできる方法はありますか?
一部の Perl モジュール (.pm) を変更する必要があります。ワークフローは、Web ページから CGI スクリプトを介して開始され、いくつかのモジュール/オブジェクトを介して入力を渡し、データを使用する必要があるモジュールで終了します。どこかでデータが変更されたので、その場所を特定する必要があります。
Perlスクリプトの現在の位置に先行するサブコールの任意の深さまでのサブ+モジュールのリストに(印刷用に)アクセスできる方法はありますか?
一部の Perl モジュール (.pm) を変更する必要があります。ワークフローは、Web ページから CGI スクリプトを介して開始され、いくつかのモジュール/オブジェクトを介して入力を渡し、データを使用する必要があるモジュールで終了します。どこかでデータが変更されたので、その場所を特定する必要があります。
Devel::StackTraceを使用できます。
use Devel::StackTrace;
my $trace = Devel::StackTrace->new;
print $trace->as_string; # like carp
これは Carp のトレースのように動作しますが、フレームをより細かく制御できます。
1 つの問題は、参照が文字列化されており、参照された値が変更された場合に表示されないことです。ただし、完全なデータを印刷するためにPadWalkerを使用していくつかのものを作成することはできます(ただし、それは巨大になります)。
このコードは、モジュールを追加しなくても機能します。必要な場所に含めるだけです。
my $i = 1;
print STDERR "Stack Trace:\n";
while ( (my @call_details = (caller($i++))) ){
print STDERR $call_details[1].":".$call_details[2]." in function ".$call_details[3]."\n";
}
Carp::longmess
あなたが望むことをします、そしてそれは標準です。
use Carp qw<longmess>;
use Data::Dumper;
sub A { &B; }
sub B { &C; }
sub C { &D; }
sub D { &E; }
sub E {
# Uncomment below if you want to see the place in E
# local $Carp::CarpLevel = -1;
my $mess = longmess();
print Dumper( $mess );
}
A();
__END__
$VAR1 = ' at - line 14
main::D called at - line 12
main::C called at - line 10
main::B called at - line 8
main::A() called at - line 23
';
私はこのサブを思いつきました (オプションの blessin' アクションが追加されました!)
my $stack_frame_re = qr{
^ # Beginning of line
\s* # Any number of spaces
( [\w:]+ ) # Package + sub
(?: [(] ( .*? ) [)] )? # Anything between two parens
\s+ # At least one space
called [ ] at # "called" followed by a single space
\s+ ( \S+ ) \s+ # Spaces surrounding at least one non-space character
line [ ] (\d+) # line designation
}x;
sub get_stack {
my @lines = split /\s*\n\s*/, longmess;
shift @lines;
my @frames
= map {
my ( $sub_name, $arg_str, $file, $line ) = /$stack_frame_re/;
my $ref = { sub_name => $sub_name
, args => [ map { s/^'//; s/'$//; $_ }
split /\s*,\s*/, $arg_str
]
, file => $file
, line => $line
};
bless $ref, $_[0] if @_;
$ref
}
@lines
;
return wantarray ? @frames : \@frames;
}
callerはそれを行うことができますが、それよりもさらに多くの情報が必要になる場合があります。
ともCarp::confess
ありCarp::cluck
ます。