¿Cómo puedo obtener una lista de pila de llamadas en Perl?
stack-trace callstack (7)
Este código funciona sin ningún módulo adicional . Solo inclúyelo donde sea necesario.
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";
}
¿Hay alguna manera de que pueda acceder (para imprimir) una lista de sub + módulo a la profundidad arbitraria de sub llamadas que preceden a una posición actual en una secuencia de comandos de Perl?
Necesito hacer cambios en algunos módulos Perl (.pm''s). El flujo de trabajo se inicia desde una página web a través de un script cgi, pasando la entrada a través de varios módulos / objetos que terminan en el módulo donde necesito usar los datos. En algún momento, los datos se cambiaron y necesito averiguar dónde.
Puedes usar Devel::StackTrace .
use Devel::StackTrace;
my $trace = Devel::StackTrace->new;
print $trace->as_string; # like carp
Se comporta como la huella de Carp, pero puedes tener más control sobre los marcos.
El único problema es que las referencias están codificadas y si un valor referenciado cambia, no lo verá. Sin embargo, podrías mejorar algunas cosas con PadWalker para imprimir la información completa (sin embargo, sería enorme).
Si bien esto no responde a tu pregunta, podría ayudarte a resolver tu problema :-)
Aquí hay un artículo interesante que describe una forma de descubrir quién cambia sus variables de Mark Dominus
También hay Carp::confess
y Carp::cluck
.
Uno que es más bonito: Devel::PrettyTrace
use Devel::PrettyTrace;
bt;
caller puede hacerlo, aunque es posible que desee obtener más información que esa.
Carp::longmess
hará lo que quieras, y es estándar.
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
'';
Se me ocurrió este sub (¡Ahora con la acción de bendición opcional!)
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;
}