如何打印所有已执行的子程序?
How can I print all executed subroutines?
例如我有以下 Perl 脚本
{
package A;
{
package B;
sub _y {
print "Just Another Perl Hacker\n";
}
}
sub _x {
print "Hello world!\n";
B::_y();
}
}
use strict;
use warnings;
_x();
如何将每个已执行的带有包限定符的子程序打印到 STDERR 或任何日志文件?
例如从上面的脚本中,我希望看到以下输出:
1 A::_x()
2 B::_y()
我认为可以使用像 Devel::NYTProf 这样的调试器,但我还没有找到用于该简单任务的特定调试器模块或它们的参数。
有什么想法吗?
考虑调试模块会让您走上正轨。启用调试模式后,Perl 在程序的每个执行步骤中调用函数 DB::DB()
。从这里您可以从 caller
内置函数中提取子例程名称(其中将包括包名称),并按照您认为合适的方式输出它。
从 @INC
路径中某处名为 Devel/AllSubs.pm
的文件开始:
package Devel::AllSubs;
my $count = 0;
my $last_sub = '::';
sub DB::DB {
my ($pkg, $file, $line,$sub) = caller(1);
if ($sub ne $last_sub) {
print STDERR ++$count," $sub\n";
$last_sub = $sub;
}
}
1;
然后运行你的程序为
$ perl -d:AllSubs script.pl
示例输出:
1 A::_x
Hello world!
2 B::_y
Just Another Perl Hacker
可以使用标准的 perl 调试器来完成:
$ PERLDB_OPTS="NonStop frame=1" perl -d prog.pl
entering CODE(0x260cd78)
entering strict::import
entering CODE(0x260cd18)
entering warnings::import
Package try.pl.
entering DB::Obj::_init
entering A::_x
Hello world!
entering B::_y
Just Another Perl Hacker
(请注意,我必须将 _x();
更改为 A::_x();
才能让您的代码变为 运行。)
如果要将输出放在文件中,请添加 LineInfo=filenamehere
。有关详细信息,请参阅 perldoc perldebug
。 (特别是,如果您将选项更改为 frame=2
,您还会收到从子例程返回的消息。)
CODE
引用是针对 use
语句周围的隐式 BEGIN
块:
use strict;
真的是
BEGIN {
require "strict.pm";
strict->import();
}
另一种解决方案,使用已经提到的 Devel::NYTProf(更准确地说,是分析器而不是调试器),它不需要您编写任何额外的代码并为您提供更多信息。
% perl -d:NYTProf yourscript.pl
这将默认创建一个 nytprof.out
文件。然后你可以这样做:
% nytprofcalls nytprof.out
这将为您提供详细的通话信息。示例脚本:
use strict;
sub f1 {
print "hi;\n";
f2();
}
sub f2 {
print "hi2\n";
}
f1();
和示例输出:
main::f1;main::f2 30
main::f1;main::CORE:print 124
main::f1;main::f2;main::CORE:print 40
main::BEGIN@1 4262
main::f1 113
main::BEGIN@1;strict::import 39
main::BEGIN@1;strict::BEGIN@7 396
main::BEGIN@1;strict::BEGIN@7;strict::CORE:match 58
您可以看到 NYTProf 还列出了对核心函数 (CORE::print) 的调用等。
作为奖励,您可以使用以下命令查看整个配置文件输出:
% nytprofhtml
然后打开报告页面,例如使用:
% firefox nytprof/index.html
您可以看到已执行的子例程(按执行时间 运行 排序)、执行次数 运行 等等。
例如我有以下 Perl 脚本
{
package A;
{
package B;
sub _y {
print "Just Another Perl Hacker\n";
}
}
sub _x {
print "Hello world!\n";
B::_y();
}
}
use strict;
use warnings;
_x();
如何将每个已执行的带有包限定符的子程序打印到 STDERR 或任何日志文件?
例如从上面的脚本中,我希望看到以下输出:
1 A::_x()
2 B::_y()
我认为可以使用像 Devel::NYTProf 这样的调试器,但我还没有找到用于该简单任务的特定调试器模块或它们的参数。
有什么想法吗?
考虑调试模块会让您走上正轨。启用调试模式后,Perl 在程序的每个执行步骤中调用函数 DB::DB()
。从这里您可以从 caller
内置函数中提取子例程名称(其中将包括包名称),并按照您认为合适的方式输出它。
从 @INC
路径中某处名为 Devel/AllSubs.pm
的文件开始:
package Devel::AllSubs;
my $count = 0;
my $last_sub = '::';
sub DB::DB {
my ($pkg, $file, $line,$sub) = caller(1);
if ($sub ne $last_sub) {
print STDERR ++$count," $sub\n";
$last_sub = $sub;
}
}
1;
然后运行你的程序为
$ perl -d:AllSubs script.pl
示例输出:
1 A::_x
Hello world!
2 B::_y
Just Another Perl Hacker
可以使用标准的 perl 调试器来完成:
$ PERLDB_OPTS="NonStop frame=1" perl -d prog.pl
entering CODE(0x260cd78)
entering strict::import
entering CODE(0x260cd18)
entering warnings::import
Package try.pl.
entering DB::Obj::_init
entering A::_x
Hello world!
entering B::_y
Just Another Perl Hacker
(请注意,我必须将 _x();
更改为 A::_x();
才能让您的代码变为 运行。)
如果要将输出放在文件中,请添加 LineInfo=filenamehere
。有关详细信息,请参阅 perldoc perldebug
。 (特别是,如果您将选项更改为 frame=2
,您还会收到从子例程返回的消息。)
CODE
引用是针对 use
语句周围的隐式 BEGIN
块:
use strict;
真的是
BEGIN {
require "strict.pm";
strict->import();
}
另一种解决方案,使用已经提到的 Devel::NYTProf(更准确地说,是分析器而不是调试器),它不需要您编写任何额外的代码并为您提供更多信息。
% perl -d:NYTProf yourscript.pl
这将默认创建一个 nytprof.out
文件。然后你可以这样做:
% nytprofcalls nytprof.out
这将为您提供详细的通话信息。示例脚本:
use strict;
sub f1 {
print "hi;\n";
f2();
}
sub f2 {
print "hi2\n";
}
f1();
和示例输出:
main::f1;main::f2 30
main::f1;main::CORE:print 124
main::f1;main::f2;main::CORE:print 40
main::BEGIN@1 4262
main::f1 113
main::BEGIN@1;strict::import 39
main::BEGIN@1;strict::BEGIN@7 396
main::BEGIN@1;strict::BEGIN@7;strict::CORE:match 58
您可以看到 NYTProf 还列出了对核心函数 (CORE::print) 的调用等。
作为奖励,您可以使用以下命令查看整个配置文件输出:
% nytprofhtml
然后打开报告页面,例如使用:
% firefox nytprof/index.html
您可以看到已执行的子例程(按执行时间 运行 排序)、执行次数 运行 等等。