【问题标题】:Can 'use strict' warn instead of error可以“使用严格”警告而不是错误
【发布时间】:2011-07-22 19:43:08
【问题描述】:

当使用use strict 时,perl 会在不安全的结构上产生运行时错误。现在我想知道是否可以让它只打印一个警告而不是导致运行时错误?还是use warnings(或-w)警告同样的问题?

【问题讨论】:

  • 你为什么需要那个?如果你真的需要no strict;,你可以对部分代码禁用严格。
  • 原因是我正在使用一个不允许停止的生产关键代码库。同时,我想同时解决这些问题。在这种情况下,通过发出警告并检查完整日志而不是:* 找到中止的运行 *修复问题 *重新运行 *等待几个小时直到在下一个问题中止等等...

标签: perl error-handling strict


【解决方案1】:

不,不能让use strict 发出警告而不是死亡。它所做的只是在神奇的$^H 变量中设置一些位,这会触发 Perl 解释器内部的各种事情。

不,use warnings 并没有警告与 use strict 杀死你一样的事情。例如,use warnings 会警告您变量只使用了一次(这可能是拼写错误的结果)。

【讨论】:

    【解决方案2】:

    我将尝试猜测这里的真正动机。如果我猜错了,请随时告诉我。

    我怀疑您尝试处理大型、较旧的代码库并希望启用限制,但您希望首先了解错误的位置(以及错误的数量)而不破坏功能。不幸的是,由于use strict 通过修改 perl 解析器和解释器的内部行为来发挥作用,因此不存在“宽松严格”或类似于 html 的任何“过渡”模式。

    但是,您可以梳理use strict 的功能,以开始朝着正确的方向前进。首先,请注意实际上有三个独立的部分:

    use strict 'refs'; # no symbolic references
    use strict 'vars'; # must declare variables
    use strict 'subs'; # no barewords
    

    其中只有 'refs' 会产生运行时错误。因此,您可以轻松地将use strict qw(vars subs) 添加到您的每个文件(脚本和模块)中,并使用perl -c 对其进行测试。如果您遇到任何错误消息,请注释掉 use strict,或者至少两个检查中的任何一个失败,并添加关于失败性质的注释并继续。通过这种方式,您可以快速(取决于文件的数量)确定哪些文件存在编译时错误,并稍后再回来解决它们。 (如果你现在比我更有动力,你甚至可以自动化这个过程)。除非你有代码在 BEGIN 块内做可怕的事情,否则这样做应该很安全。

    比较棘手的部分是检查use strict 'refs' 生成的运行时错误,不幸的是,确实没有一种简单的方法可以做到这一点,因为错误是由符号引用触发的,而符号引用不能由任何类型的静态确定分析so -c 和/或Perl::Critic 都是没用的。

    希望这更接近于解决您的实际问题。

    【讨论】:

    • 谢谢,您的猜测完全正确。目前我不能只允许这段代码中出现运行时错误,但我确实想最终朝着使用 strict 的方向前进。使用“perl -c”进行检查已经到位,因此跳过 refs 将是第一步。
    【解决方案3】:

    warningsstrict 编译指示是互补的,而不是重叠的。 strict pragma 同时具有编译时和运行时效果。您无法将限制的严重性从错误降低到警告,但您可以完全禁用它们。例如,如果您正在编写自己的导出例程,则需要启用符号引用才能操作符号表。

    {
        no strict 'refs';
        # symrefs okay within this block
    }
    

    警告也可以在词法上禁用(假设您使用use warnings 而不是大部分已过时的-w 标志)。

    严格和警告提供了一个安全网。这就是为什么建议默认使用它们的原因。如果您禁用它们,您应该只禁用必要的部分并将更改限制在尽可能小的范围内。

    【讨论】:

      【解决方案4】:

      首选方法:

      use Carp;
      
      sub foo {
        croak "no args" unless @_;
      }
      
      eval foo();
      if( $@ ){
        print "caught die: $@";
      }
      

      如果您无法将die 更改为croak

      sub foo {
        die "no args" unless @_;
      }
      
      {
        my $prev_die = $SIG{__DIE__};
        $SIG{__DIE__} = sub { print "caught die: $_[0]"; };
        eval foo();
        $SIG{__DIE__} = $prev_die;
      }
      

      第二种方法会在STDERR上打印出错误。

      见:

      perldoc -f eval

      perldoc perlvar 并搜索 /\$\@//__DIE__/

      perldoc Carp

      【讨论】:

      • 这应该如何避免由 'use strict' 引起的运行时错误?
      【解决方案5】:

      警告可以是致命的——参见perllexwarn——但严格的错误不能是非致命的。

      你为什么要这样做?我怀疑是 XY 问题。

      【讨论】:

      • 见主要问题下的评论;基本上我想慢慢迁移到使用严格的。不允许当前代码在出现这些严格错误时立即中止。
      • @Zitrax,然后慢慢添加use strict;(或者慢慢删除no strict;)。忽略警告没有任何好处。
      猜你喜欢
      • 2020-03-16
      • 2016-01-05
      • 1970-01-01
      • 2016-09-16
      • 2017-04-26
      • 1970-01-01
      • 2018-12-23
      • 2021-11-24
      相关资源
      最近更新 更多