内容

名称

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中找到的描述匹配的警告)只显示一次(没有重复的描述)。 用户代码生成的警告(如 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进行后处理,因此没有必要能够启用() 或禁用() 处理。

与 pragma 不同,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 日。