我怎样才能得到在Perl中的调用堆栈列表?
有没有一种方法,我可以访问(打印输出)sub +模块列表任意深度的子脚本之前的Perl脚本中的当前位置?
我需要修改一些Perl模块(.pm's)。 工作stream程是通过一个CGI脚本从一个网页开始的,将input传递到需要使用数据的模块中的几个模块/对象。 数据发生了变化,我需要找出在哪里。
你可以使用Devel :: StackTrace 。
use Devel::StackTrace; my $trace = Devel::StackTrace->new; print $trace->as_string; # like carp
它的行为跟鲤鱼的踪迹一样,但是你可以更好地控制帧。
一个问题是引用是string化的,如果引用的值发生变化,你将不会看到它。 不过,你可以用PadWalker打出一些东西来打印出完整的数据(尽pipe如此,这将是巨大的)。
来电者可以做到这一点,虽然你可能需要更多的信息。
还有Carp::confess
和Carp::cluck
。
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; }
虽然这不能回答你的问题,但它可能会帮助你解决你的问题:-)
这里有一篇有趣的文章描述了如何从Mark Dominus中找出谁改变了你的variables
这段代码没有任何额外的模块 。 只要包括在需要的地方。
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"; }
一个更漂亮的: Devel :: PrettyTrace
use Devel::PrettyTrace; bt;