内容

名称

diagnostics, splain - 生成详细的警告诊断

概要

使用 diagnostics 编译指示

use diagnostics;
use diagnostics -verbose;

enable  diagnostics;
disable diagnostics;

使用 splain 独立过滤器程序

perl program 2>diag.out
splain [-v] [-p] diag.out

使用 diagnostics 从行为异常的脚本获取堆栈跟踪

perl -Mdiagnostics=-traceonly my_script.pl

描述

diagnostics 编译指示

此模块扩展了 Perl 编译器和 Perl 解释器(从使用 -w 开关或 use warnings 运行 Perl 时)通常发出的简短诊断信息,用 perldiag 中更具解释性和更具吸引力的描述来增强它们。与其他编译指示一样,它影响程序的编译阶段,而不仅仅是执行阶段。

要在您的程序中用作编译指示,只需调用

use diagnostics;

在程序的开头(或接近开头)。(请注意,这确实启用了 perl 的-w标志。)然后您的整个编译将受到增强诊断的约束(: -))。这些仍然输出到STDERR

由于运行时和编译时问题之间的交互,并且因为它可能不是一个好主意,因此您不能使用no diagnostics在编译时将其关闭。但是,您可以使用 disable() 和 enable() 方法分别在运行时控制其行为,以将其关闭和打开。

-verbose标志首先打印出perldiag介绍,然后再打印任何其他诊断信息。$diagnostics::PRETTY 变量可以为寻呼机生成更漂亮的转义序列。

从 perl 本身(或更准确地说,那些与perldiag中找到的描述匹配的警告)仅显示一次(没有重复的描述)。用户代码生成的警告 a la warn() 不会受到影响,允许显示重复的用户消息。

此模块还在 perl 死亡时将堆栈跟踪添加到错误消息中。这对于查明导致死亡的原因很有用。-traceonly(或仅-t)标志关闭警告消息的解释,只留下堆栈跟踪。因此,如果您的脚本正在死亡,请使用以下命令再次运行它

perl -Mdiagnostics=-traceonly my_bad_script

查看死亡时的调用堆栈。通过提供-warntrace(或仅-w)标志,任何发出的警告也将附带堆栈跟踪。

splain程序

另一个程序splain实际上只是对(可执行的)diagnostics.pm模块的链接,以及对diagnostics.pod文档的链接。-v标志类似于use diagnostics -verbose指令。-p标志类似于$diagnostics::PRETTY 变量。由于您使用splain进行后处理,因此没有意义能够启用() 或禁用() 处理。

与编译指示不同,splain的输出被定向到STDOUT

示例

以下文件肯定会同时在运行时和编译时触发一些错误

use diagnostics;
print NOWHERE "nothing\n";
print STDERR "\n\tThis message should be unadorned.\n";
warn "\tThis is a user warning";
print "\nDIAGNOSTIC TESTER: Please enter a <CR> here: ";
my $a, $b = scalar <STDIN>;
print "\n";
print $x/$y;

如果您希望先运行程序,然后再查看其问题,请执行以下操作

perl -w test.pl 2>test.out
./splain < test.out

请注意,这在一般情况下在血统更可疑的 shell 中是不可能的,因为理论上

(perl -w test.pl >/dev/tty) >& test.out
./splain < test.out

因为您只是将现有的stdout移动到了其他地方。

如果您不想修改源代码,但仍然需要即时警告,请执行以下操作

exec 3>&1; perl -w test.pl 2>&1 1>&3 3>&- | splain 1>&2 3>&- 

很巧妙,对吧?

如果您想即时控制警告,请执行以下操作。确保您首先执行use,否则您将无法访问 enable() 或 disable() 方法。

    use diagnostics; # checks entire compilation phase 
	print "\ntime for 1st bogus diags: SQUAWKINGS\n";
	print BOGUS1 'nada';
	print "done with 1st bogus\n";

    disable diagnostics; # only turns off runtime warnings
	print "\ntime for 2nd bogus: (squelched)\n";
	print BOGUS2 'nada';
	print "done with 2nd bogus\n";

    enable diagnostics; # turns back on runtime warnings
	print "\ntime for 3rd bogus: SQUAWKINGS\n";
	print BOGUS3 'nada';
	print "done with 3rd bogus\n";

    disable diagnostics;
	print "\ntime for 4th bogus: (squelched)\n";
	print BOGUS4 'nada';
	print "done with 4th bogus\n";

内部机制

诊断消息来自运行时可用的perldiag.pod文件。否则,它们可能在构建splain包时嵌入到文件中本身。有关详细信息,请参阅Makefile

如果发现现有的 $SIG{__WARN__} 处理程序,它将继续被尊重,但仅在 diagnostics::splainthis() 函数(模块的 $SIG{__WARN__} 拦截器)对您的警告进行处理之后。

如果您非常想知道正在拦截哪些内容,可以设置一个 $diagnostics::DEBUG 变量。

BEGIN { $diagnostics::DEBUG = 1 } 

错误

无法说“no diagnostics”很烦人,但这可能并非不可克服。

-pretty 指令调用得太晚,无法影响此事。您必须这样做,并且在加载模块之前

BEGIN { $diagnostics::PRETTY = 1 } 

我可以通过延迟编译直到需要它来更快地启动,但这在 Perl 5.001e 中使用 pragma 形式时会得到“panic: top_level”。

虽然这份文档确实有点不严肃,但如果您使用名为splain的程序,您应该期待一些奇思妙想。

作者

Tom Christiansen <[email protected]>,1995 年 6 月 25 日。