我如何有条件地使警告致命?

时间:2014-02-03 23:27:41

标签: perl

我希望有致命的错误,可以降级为警告(或相反,警告可以提升为致命错误),具体取决于用户的偏好。目前,我正在使用die并将其覆盖如下:

my $force;
BEGIN {
    no warnings 'once';
    Getopt::Long::Configure('pass_through');
    GetOptions('force', \$force);
    *CORE::GLOBAL::die = sub { warn @_ } if $force;
    Getopt::Long::Configure('no_pass_through');
}

use My::Module;
...
die "maybe";
...
exit(1) if $force;
exit(0); # success!

我不喜欢这种方法,主要是因为有一些地方我仍然想死(例如缺少命令行参数)。我宁愿将die的实例更改为warn并执行条件use warnings FATAL => 'all' 1 。问题是use warnings是词法范围的,所以这是无效的:

if (!$force) {
    use warnings FATAL => 'all';
}

尝试使用postfix条件是语法错误:

use warnings FATAL => 'all' unless $force;

use不能在表达式中使用:

$force or use warnings FATAL => 'all';  # syntax error

我可以想到各种令人反感的解决方法(定义我自己的警告/死亡,在if / else中复制我的主要脚本代码等)但我正在寻求一种优雅的解决方案,有条件地应用use warnings目前的词汇范围。 (在父范围中应用它也会起作用,但可能需要黑魔法。)

<小时/> 1:实际上,我想将use warnings::register添加到我的模块中,use warnings FATAL => 'My::Module'添加到我的脚本中,但这个区别对于这个问题的目的并不重要。

1 个答案:

答案 0 :(得分:4)

你可以尝试:

use if !$force, warnings => qw( FATAL all );

是的,有一个名为if的模块与Perl一起分发,以便很容易进行条件导入。

请注意,这是在编译时进行评估的,因此需要在编译时定义$force。 (可能在BEGIN { ... }区块内。)根据您问题中的代码示例,您似乎已经考虑到了这一部分。

或者,更多手册:

BEGIN {
    require warnings;
    warnings->import(qw/ FATAL all /) unless $force;
}

完全不同的方法是使用信号处理程序$SIG{__WARN__}$SIG{__DIE__}来判断是否在运行时死亡。