Perl在运行时每次调用时打印出所有subs参数

时间:2015-05-11 06:15:31

标签: perl

我正在寻找调试从命名空间Myapp::*打印每个子例程调用的方法(例如,不转储CPAN模块),但无需手动编辑每个.pm文件用于插入一些模块或打印语句。

我只是学习(更好地说:试图理解)package DB,是什么让我跟踪执行(使用shebang #!/usr/bin/perl -d:Mytrace

package DB;
use 5.010;

sub DB {
    my( $package, $file, $line ) = caller;
    my $code = \@{"::_<$file"};
    print STDERR "--> $file $line $code->[$line]";
}

#sub sub {
#    print STDERR "$sub\n";
#    &$sub;
#}

1;

并寻找一种方法如何使用sub调用从sub的命名空间打印被调用Myapp::*的实际参数。

或者这里有一些更容易(常见)的方法

  • 合并执行行跟踪器DB::DB
  • 使用每个子程序调用参数的转储(及其返回值,如果可能)?

1 个答案:

答案 0 :(得分:3)

我不知道这个单词的任何理智含义是否“更容易”,但你可以遍历符号表并将所有函数包装在打印其参数和返回值的代码中。以下是如何完成的示例:

#!/usr/bin/env perl

use 5.14.2;
use warnings;

package Foo;

sub first {
    my ( $m, $n ) = @_;

    return $m+$n;
}

sub second {
    my ( $m, $n ) = @_;

    return $m*$n;
}

package main;

no warnings 'redefine';

for my $k (keys %{$::{'Foo::'}}) {
    my $orig = *{$::{'Foo::'}{$k}}{CODE};
    $::{'Foo::'}{$k} = sub {
        say "Args: @_";
        unless (wantarray) {
            my $r = $orig->(@_);
            say "Scalar return: $r";
            return $r;
        }
        else {
            my @r = $orig->(@_);
            say "List return: @r";
            return @r
        }
    }
}

say Foo::first(2,3);
say Foo::second(4,6);