문제

PERL 스크립트의 현재 위치에 앞서 임의의 서브 콜에 대한 서브 + 모듈 목록에 액세스 할 수있는 방법이 있습니까?

일부 Perl 모듈 (.pm)을 변경해야합니다. 워크 플로는 CGI 스크립트를 통해 웹 페이지에서 시작하여 데이터를 사용해야하는 모듈에서 끝나는 여러 모듈/객체를 통해 입력을 전달합니다. 라인을 따라 어딘가에 데이터가 변경되었고 어디에 있는지 알아야합니다.

도움이 되었습니까?

해결책

당신이 사용할 수있는 개발 :: 스택 트레이스.

use Devel::StackTrace;
my $trace = Devel::StackTrace->new;
print $trace->as_string; # like carp

잉어의 흔적처럼 작동하지만 프레임을 더 많이 제어 할 수 있습니다.

한 가지 문제는 참조가 문을 닫고 참조 된 값이 변경되면 볼 수 없다는 것입니다. 그러나 당신은 몇 가지 물건을 채울 수 있습니다 Padwalker 전체 데이터를 인쇄하려면 (큰 일이 될 것입니다).

다른 팁

방문객 그보다 더 많은 정보를 원할 수도 있지만 그렇게 할 수 있습니다.

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
';

나는이 서브를 생각해 냈다 (이제 선택적인 축복의 행동으로!)

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;
}

또한 있습니다 Carp::confess 그리고 Carp::cluck.

이 코드는 작동합니다 추가 모듈없이. 필요한 곳에 포함하십시오.

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";
}

더 예쁘다 : 개발 :: 예쁜 트레이스

use Devel::PrettyTrace;
bt;

비 코어 모듈을 사용할 수 없거나 피하고 싶은 경우 다음은 다음과 같이 생각해 낸 간단한 서브 루틴입니다.

#!/usr/bin/perl
use strict;
use warnings;

sub printstack {
    my ($package, $filename, $line, $subroutine, $hasargs, $wantarray, $evaltext, $is_require, $hints, $bitmask, $hinthash);
    my $i = 1;
    my @r;
    while (@r = caller($i)) {
        ($package, $filename, $line, $subroutine, $hasargs, $wantarray, $evaltext, $is_require, $hints, $bitmask, $hinthash) = @r;
        print "$filename:$line $subroutine\n";
        $i++;
    }
}

sub i {
    printstack();
}

sub h {
    i;
}

sub g {
    h;
}

g;

다음과 같이 출력을 생성합니다.

/root/_/1.pl:21 main::i
/root/_/1.pl:25 main::h
/root/_/1.pl:28 main::g

또는 oneliner :

for (my $i = 0; my @r = caller($i); $i++) { print "$r[1]:$r[2] $r[3]\n"; }

발신자에 대한 문서를 찾을 수 있습니다 여기.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top