使用$ @在模块中传递错误消息

时间:2014-04-04 06:14:00

标签: perl

我一直在研究一个现在没有维护的CPAN模块的分支(据我所知)。在此模块中,他们使用$@将错误消息传递到堆栈中。换句话说,如果在对子程序的任何调用中出现任何问题,它们会设置$@,并且在调用之后检查它是否已设置。我之前从未见过这个变量,但我觉得它很有用,所以我开始在代码中使用它。现在我最近读了一些关于它的内容,发现它的目的比这更狭窄。阅读perlvar(以及其他有关此问题的SO问题)对我来说并没有完全回答这个问题,但是,以这种方式使用$@是否可以?一些"标点符号"我知道的变量肯定以这种通用方式使用(有些甚至用local),这是其中一种情况,还是我可以继续这种做法吗?

2 个答案:

答案 0 :(得分:4)

通常不会明确设置

$@。而是在引发异常时自动为您设置。来自perldoc die

  
      
  • 死LIST

         

    die引发了异常。在eval内部,错误消息被填充到$@中,eval以未定义的值终止。如果异常在所有封闭eval之外,则未捕获的异常将LIST打印到STDERR并以非零值退出。如果您需要使用特定退出代码退出流程,请参阅exit

  •   

例如,

#!/usr/bin/perl

eval {
    print "Hi\n";
    die "Something went wrong here";
    print "Bye\n";
};
print $@;

打印

Hi
Something went wrong here at ./cr22854919 line 5.

允许使用$@以这种方式将错误消息传递到堆栈中,作为一种try-catch机制。但是,由于它是一个全局变量,因此应在eval { }块之后尽快处理它,以确保没有其他代码干扰您对异常的处理。


通常用于错误处理的另一个神奇变量是$!,其作用类似于C中的errno

示例:

my $path = "/tmp/no-such-file";
open F, '<', $path
    or print STDERR "$path: $!\n";

输出:

/tmp/no-such-file: No such file or directory

答案 1 :(得分:1)

$@是Perl中相对“非特殊”的特殊变量。 Perl中的任何内容都没有从$@读取,并且最后只有eval {}块写入。这使得它可以相对安全地用于您自己的错误信号目的。

特别是,模块的核心IO::Socket树使用它来指示构造函数的失败:

use IO::Socket::IP;
my $sock = IO::Socket::IP->new(...) or die "Cannot connect - $@";

更传统的$!在这里不合适,因为$!具有包装libc级errno结构的魔力;意味着它只能设置为整数errno值,即使它可以读作数字或字符串。因为有时可能会发生与errno值没有直接关系的失败(例如,在IO::Socket的情况下,例如多种解析器失败),有时候$!不适合这种情况。 / p>