第九章 管理真实的程序(二) -告警

处理告警

Perl的写法不止一种,有的方式让人迷惑,有的甚至不正确。Perl的告警系统可以帮你避免这些情况的发生。

产生告警

使用内置关键字 warn 产生一个告警:

warn 'Something went wrong!';

warn会将列表值输出到STDERR句柄(标准错误输出)。除非列表的最后一个元素以换行符结尾,否则Perl还会在告警中带上文件名和warn所在行号来帮助定位问题。

核心模块Carp扩展了Perl的告警机制。它的函数carp(),从调用的角度报告一个告警信息。

use Carp 'carp';
sub only_two_arguments
{
my ($lop, $rop) = @_;
carp( 'Too many arguments provided' ) if @_ > 2;
...
}

告警信息将会包含文件名和调用代码的行号。还有个函数cluck()功能类似,但是它会包含回溯所有当前函数的调用者。

Carp的详细模式会将整个文件的carp()和croak()产生的告警信息加上回溯信息:

$ perl -MCarp=verbose my_prog.pl

写模块时建议使用Carp来替代warn和die。

注入Carp
有时候你要调试一些未使用carp()和croak()的代码。这种情况下,使用Carp::Always模块来为所有的warn或die增加回溯信息:

perl -MCarp::Always some_program.pl

启用和禁用告警

有的老代码会使用-w命令行参数。-w参数将使整个程序启用告警,即使是外部别人写的模块。如果你有时间和精力去消除所有代码库的告警,那当然好,否则信息太多反而会淹没了你的关注点。在很多年里,-w参数是启用告警的唯一手段。

现代更好的方式是使用warnings编译指示来启用告警,这样就能在一定范围内(词法范围内)启用告警机制,范围之外的则不受影响。

全局告警标识
-W参数会无视任何warngins编译指示,强制整个程序启用告警。
-X参数则会强制整个程序禁用告警。
它们都不常见。

-w,-W,-X 都会设置全局变量$W。在编译指示warnings出现之前,通常会将变量$W本地化赋值,来控制作用范围。

禁用告警类别

要在词法范围内禁用指定类型的告警,使用no warnings后面跟指定的类型参数列表。

perldoc perllexwarn可查看当前版本Perl所支持的告警种类。有些警告可能没有什么实际的作用,比如递归的警告(recursion)--调用自身超过100次就会触发该警告。如果你写的程序可以正常终止,但是次数可能超过100,这时你就需要禁用此类警告。

如果你的程序会生成代码,或者重新定义了符号引用,你可能想要禁用redefine警告。

一些有经验的Perl程序员可能会禁用 uninitialized警告,因为字符串的值的来源有很多。如果你总是很注意初始化你的变量,你就永远不需要禁用这类警告。

提升告警的严重性

如果你的项目需要将告警的严重性升级,那么可以将告警提升为致命错误。(告警可以认为是一种提示信息,而致命错误则要求你必须修复)在词法范围内将所有种类的告警信息提升为致命错误:

use warnings FATAL => 'all';

你也可仅将指定类别的告警信息提升为致命错误:

use warnings FATAL => 'deprecated';

有了这些纪律,就能构建健壮的代码--但还是要谨慎,因为很多的告警信息的产生依赖于运行时条件。如果你的测试条目未能覆盖所有可能的警告,那么你的程序可能在运行时会因为异常而退出。
新版Perl增加了新的告警并且可以配置提升告警为致命错误。

捕获告警

如果有需要,你还可以捕获告警。变量%SIG保存有信号处理的信息, 我们可以通过设置$SIG{WARN} 的处理程序来捕获告警:

{
my $warning;
local $SIG{__WARN__} = sub { $warning .= shift };
# do something risky
...
say "Caught warning:\n$warning" if $warning;
}

告警的处理程序中,第一个参数就是告警的内容。
有点要注意的是: %SIG是一个全局变量。

自定义告警

编译指示warnings::register允许你创建自己的告警:

package Scary::Monkey;
use warnings::register;

这样就会创建一个叫 Scary::Monkey的告警类。
启用这个警告:

use warnings 'Scary::Monkey'; 

禁用这个警告:

no warnings 'Scary::Monkey';

warnings::enabled()用来测试在调用者的词法访问内是否启用了告警类。 warnings::warnif()如果告警有效就产生一个告警信息。例如,在deprecated类中产生一个警告:

package Scary::Monkey;

use warnings::register;

sub import
{
warnings::warnif( 'deprecated', 'empty imports from ' . __PACKAGE__ . ' are now deprecated' )
unless @_;
}

perldoc perllexwarn可查看更多细节。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容