Carp - 模块的替代 warn 和 die
use Carp;
# warn user (from perspective of caller)
carp "string trimmed to 80 chars";
# die of errors (from perspective of caller)
croak "We're outta here!";
# die of errors with stack backtrace
confess "not implemented";
# cluck, longmess and shortmess not exported by default
use Carp qw(cluck longmess shortmess);
cluck "This is how we got here!"; # warn with stack backtrace
my $long_message = longmess( "message from cluck() or confess()" );
my $short_message = shortmess( "message from carp() or croak()" );
Carp 例程在您自己的模块中很有用,因为它们的行为类似于 die()
或 warn()
,但消息更有可能对您的模块用户有用。在 cluck()
和 confess()
的情况下,该上下文是调用堆栈中每个调用的摘要;longmess()
返回错误消息的内容。
对于更短的消息,您可以使用 carp()
或 croak()
,它们将错误报告为来自调用您的模块的位置。shortmess()
返回此错误消息的内容。不能保证这就是错误发生的位置,但这是一个很好的猜测。
Carp
在组装错误消息的过程中,会小心地避免覆盖状态变量 $!
和 $^E
。这意味着,如果需要增强错误消息,并且调用 Carp
的代码在这些变量中留下了有用的值,那么 $SIG{__DIE__}
或 $SIG{__WARN__}
处理程序可以捕获这些变量中保存的错误信息。当然,Carp
无法保证后者。
您还可以通过更改 Carp
命名空间中的一些全局变量来更改 Carp
的输出和逻辑方式。请参阅下面关于 "全局变量" 的部分。
以下是关于 carp
和 croak
工作原理的更完整描述。它们的工作原理是在调用堆栈中搜索函数调用堆栈,直到找到一个没有被告知不应该出现错误的调用堆栈。如果所有调用都被标记为安全,它们就会放弃并返回完整的堆栈回溯。换句话说,它们假设第一个看起来像潜在嫌疑人的调用就是罪魁祸首。它们用于判断调用是否不应该生成错误的规则如下:
任何来自包到自身的调用都是安全的。
包声明,对包含在 @CARP_NOT
中的包或(如果该数组为空)@ISA
中的包的调用不会出现错误。覆盖 @ISA
的能力是 5.8 中的新功能。
第 2 项中的信任是可传递的。如果 A 信任 B,B 信任 C,那么 A 也信任 C。因此,如果您没有使用 @CARP_NOT
覆盖 @ISA
,那么这种信任关系就等同于“继承自”。
任何来自内部 Perl 模块的调用都是安全的。(没有什么可以阻止用户模块将自己标记为 Perl 的内部模块,但这种做法不建议。)
任何对 Perl 的警告系统的调用(例如 Carp 本身)都是安全的。(这条规则可以防止它在您调用 carp
或 croak
的地方报告错误。)
$Carp::CarpLevel
可以设置为跳过固定数量的额外调用级别。不建议使用此方法,因为它很难让它正常工作。
作为调试辅助工具,您可以强制 Carp 将所有模块的 croak 视为 confess,将 carp 视为 cluck。换句话说,强制提供详细的堆栈回溯。这在尝试理解警告或错误的生成原因或位置时非常有用。
此功能通过“导入”不存在的符号“verbose”来启用。您通常可以通过以下方式启用它:
perl -MCarp=verbose script.pl
或者在 PERL5OPT 环境变量中包含字符串 -MCarp=verbose
。
或者,您可以将全局变量$Carp::Verbose
设置为 true。请参阅下面的"全局变量"部分。
在每个堆栈级别,子例程的名称与其参数一起显示。对于简单的标量,这已经足够了。对于复杂的数据类型,例如对象和其他引用,这可能只显示'HASH(0x1ab36d8)'
。
Carp 提供了两种方法来控制这一点。
对于对象,如果存在,将调用方法CARP_TRACE
。如果此方法不存在,或者它递归到Carp
,或者它以其他方式抛出异常,则跳过此步骤,Carp 继续执行下一个选项,否则检查停止,并使用返回的字符串。建议对象类型是字符串的一部分,以方便调试。
对于任何类型的引用,都会检查$Carp::RefArgFormatter
(见下文)。此变量应为代码引用,并将传入当前参数。如果此函数不存在(变量为 undef),或者它递归到Carp
,或者它以其他方式抛出异常,则跳过此步骤,Carp 继续执行下一个选项,否则检查停止,并使用返回的字符串。
否则,如果CARP_TRACE
和$Carp::RefArgFormatter
均不可用,则忽略任何重载,将值转换为字符串。
此变量决定在输出中显示多少个字符串评估字符。使用值0
显示所有文本。
默认值为0
。
此变量决定打印每个函数参数的字符数。使用值0
显示参数的完整长度。
默认值为64
。
此变量决定显示每个函数的多少个参数。使用假值显示函数调用中的所有参数。要抑制所有参数,请使用-1
或'0 but true'
。
默认值为8
。
此变量使carp()
和croak()
生成堆栈回溯,就像cluck()
和confess()
一样。这就是use Carp 'verbose'
在内部实现的方式。
默认值为0
。
此变量设置一个通用的参数格式化程序来显示引用。简单的标量和实现了 CARP_TRACE
的对象不会经过此格式化程序。不支持从该函数内部调用 Carp
。
local $Carp::RefArgFormatter = sub {
require Data::Dumper;
Data::Dumper->Dump($_[0]); # not necessarily safe
};
此变量,在您的包中,表示哪些包不被视为错误的位置。carp()
和 cluck()
函数在报告错误发生位置时会跳过调用者。
注意:此变量必须在包的符号表中,因此
# These work
our @CARP_NOT; # file scope
use vars qw(@CARP_NOT); # package scope
@My::Package::CARP_NOT = ... ; # explicit package variable
# These don't work
sub xyz { ... @CARP_NOT = ... } # w/o declarations above
my @CARP_NOT; # even at top-level
使用示例
package My::Carping::Package;
use Carp;
our @CARP_NOT;
sub bar { .... or _error('Wrong input') }
sub _error {
# temporary control of where'ness, __PACKAGE__ is implicit
local @CARP_NOT = qw(My::Friendly::Caller);
carp(@_)
}
这将使 Carp
报告错误来自不在 My::Carping::Package
或 My::Friendly::Caller
中的调用者。
另请阅读上面的 "DESCRIPTION" 部分,了解 Carp
如何决定从哪里报告错误。
使用 @CARP_NOT
,而不是 $Carp::CarpLevel
。
覆盖 Carp
对 @ISA
的使用。
这表示哪些包是 Perl 的内部包。Carp
永远不会将错误报告为来自 Perl 内部包中的行。例如
$Carp::Internal{ (__PACKAGE__) }++;
# time passes...
sub foo { ... or confess("whatever") };
将从第一个不在 __PACKAGE__ 中的调用者开始提供完整的堆栈回溯。(除非该包也是 Perl 的内部包。)
这表示哪些包是 Perl 警告系统的内部包。对于生成完整的堆栈回溯,这与 Perl 内部相同,堆栈回溯不会从列在 %Carp::CarpInternal
中的包内部开始。但对于 carp
或 croak
生成的摘要消息来说,它略有不同。这些错误不会在调用 %Carp::CarpInternal
中的包的任何行上报告。
例如,Carp
本身列在 %Carp::CarpInternal
中。因此,confess
的完整堆栈回溯不会从 Carp
内部开始,并且调用 croak
的简短消息不会放在调用 croak
的行上。
此变量决定在报告错误发生在调用 Carp
函数时跳过多少个额外的调用帧,这些调用帧在其他情况下不会被跳过。在生成完整堆栈回溯的调用中计算这些调用帧相当容易。但是,对于生成简短消息的调用,进行此类计算要困难得多。通常人们会跳过太多调用帧。如果他们幸运的话,他们跳过的调用帧足够多,以至于 Carp
会遍历整个调用堆栈,意识到有错误,然后生成完整的堆栈回溯。如果他们不幸的话,错误将从调用堆栈中非常高的误导性位置报告。
因此,最好避免使用 $Carp::CarpLevel
。而是使用 @CARP_NOT
、%Carp::Internal
和 %Carp::CarpInternal
。
默认值为0
。
Carp 例程目前不处理异常对象。如果以第一个参数为引用调用,它们将简单地调用 die() 或 warn(),具体取决于情况。
Carp 由 perl 5 维护者维护,作为核心 perl 5 版本控制库的一部分。请参阅 perlhack perldoc,了解如何提交补丁并为其做出贡献。
Carp 模块首次出现在 Larry Wall 的 perl 5.000 发行版中。从那时起,它被几个 perl 5 维护者修改过。Andrew Main (Zefram) <[email protected]> 将 Carp 分离成一个独立的发行版。
Copyright (C) 1994-2013 Larry Wall
Copyright (C) 2011, 2012, 2013 Andrew Main (Zefram) <[email protected]>
此模块是免费软件;您可以根据与 Perl 本身相同的条款重新分发和/或修改它。