如何简明扼要地检查警告类别,直到包中层次结构的根目录?

How do I concisely check warning categories up to the root of the hierarchy in my package?

提问人:cxw 提问时间:6/12/2019 最后编辑:cxw 更新时间:6/13/2019 访问量:82

问:

我知道如何为我的模块创建自定义警告类别。但是,如果我创建警告类别并使用警告,则不会抑制警告。我怎样才能简明扼要地检查两者和?use warnings::registerModule::categorywarnif()no warnings 'Module'Module::categoryModule

MCVE的

package Provider;
use strict; use warnings;

use warnings::register qw(undefined);

sub foo {
    warnings::warnif('Provider::undefined', "Undefined parameter!");
}

package Consumer;
use strict; use warnings;

Provider::foo;      # warns - OK

{
    no warnings 'Provider::undefined';
    Provider::foo;  # does not warn - OK
}

{
    no warnings 'Provider';
    Provider::foo;  # _DOES_ warn - oops  <===========
}

其他检查

如果我检查里面的警告状态,我看到它没有触及:Provider::foo()no warnings 'Provider'Provider::undefined

sub foo {
    print "$_: @{[warnings::enabled($_) ? 'enabled' : 'disabled']}\n"
        foreach qw(Provider::undefined Provider);
 }

Provider::undefined: enabled
Provider: enabled
Provider::undefined: disabled
Provider: enabled
Provider::undefined: enabled
Provider: disabled

对于上述三个测试。

解决方法

sub foo {
    my $should_warn = 1;
    foreach (qw(Provider::undefined Provider)) {
        if(!warnings::enabled($_)) {
            $should_warn = 0;
            last;
        }
    }
    warnings::warn('Provider::undefined', "Undefined parameter!")
        if $should_warn;
}

...但在我将其包装在一个模块中并将其放在 CPAN 上之前,我想知道是否有其他人已经这样做了,或者知道更好的方法:)。谷歌和SO搜索都无济于事。

Perl 警告层次 结构 编译指示

评论

0赞 Grinnz 6/12/2019
有趣的是,核心警告类别是分层的,但似乎没有在包名称类别下注册已注册的包子类别。也许这可能是一个功能请求。
0赞 cxw 6/12/2019
@Grinnz我自己也在考虑这个问题 - 我还没有使用过 perlbug,所以也许是时候:)

答:

2赞 zdim 6/12/2019 #1

该声明引入了两类新的警告,以及 .因此,请检查两者use warnings::register qw(undefined);'Provider''Provider::undefined'

sub foo {
    if (warnings::enabled('Provider') and 
        warnings::enabled('Provider::undefined')) 
    {
        warnings::warn('Undefined parameter');
    }   
}

如果禁止显示其中任一类别,则不会触发此操作

{
    no warnings 'Provider';               # EITHER stops it
    #no warnings 'Provider::undefined';

    Provider::foo;                        # does not warn
}

要要求两者停止它们,请在 中使用 条件。no warningsor::enabledfoo


例如,为了减少输入模块的 subs,您可以为此设置一个实用程序 subProvider

my $to_warn = sub  {
    return 0 if not warnings::enabled(__PACKAGE__);
    warnings::enabled(__PACKAGE__ . '::' . $_) 
        or return 0  for @_;
    return 1;
};

然后就可以了

warnings::warn('Undefined parameter') if $to_warn->('undefined');

可以在 中设置更多默认值。现在根本不需要输入名称:)$to_warnProvider

回想一下,必须在使用之前定义,或者至少预先声明。$to_warn

评论

0赞 cxw 6/12/2019
当然 - 就像我正在考虑的另一种解决方法一样,即.你知道有一个模块可以做到这一点,并防止我不得不重复吗?List::MoreUtils::all { $_ } map { warnings::enabled($_) } qw(Provider::undefined Provider)Provider
0赞 zdim 6/12/2019
@cxw 通过引入两类警告,并且(一遍又一遍地输入它确实很糟糕!我想你必须把两者都说出来?当然,可以在模块本身中编写一个实用的 sub,以减少 sub 中的输入。use warnings::register qw(undefined);'Provider''Provider::undefined'
1赞 zdim 6/12/2019
@cxw 是倒退的,固定的。添加了一个示例实用程序 sub 以减少键入