2011-05-28 44 views
3

我有一个Perl脚本中可能会出现__WARN__彼此靠近的2行。如果第一个抛出,那么我想从函数返回,而不是尝试继续。在Perl中捕捉信号的最优雅方式是什么?

我知道如何建立一个处理都行之前,所以我可以报告错误等:

local $SIG{__WARN__} = sub { 
    my $e = shift; 
    # log the error etc. 
    return; 
}; 
# possibly warning-resulting line 1 
# possibly warning-resulting line 2 

但随后发生这种情况的两条线。我宁愿它只是抓到第一个实例并从函数返回。但是该处理程序中的返回只返回处理程序,而不是外部函数。

处理信号时有没有办法从函数中返回?

+1

你期望什么样的警告?如果您从一开始就知道发生警告的原因,为什么不在执行第1行和第2行之前在您的子目录中进行说明? – Dallaylaen 2011-05-28 10:31:19

回答

1

不,你不能强制调用者返回。 (好吧,我相信你可以用正确的黑魔法XS咒语,但不要!)

这似乎是一个误导性的设计;警告不应该是致命的错误,当然不应该这样使用。

+2

你甚至可以在没有黑魔法的情况下使用警告FATAL =>'all''。有了它,任何警告抛出和可以相应处理的异常。 – bvr 2011-05-28 10:03:32

+0

够公平的,尽管我很犹豫,认为这是一个“回报”。有关此计划结构的更多信息将会有所帮助。 – Eevee 2011-05-28 21:08:51

0

只是抛出一个异常并捕获并返回调用者。

使处理程序返回一个值并检查它是否在eval之后的if语句中返回。

实际上,你甚至不必从处理程序中返回一个值,因为它并不决定是否返回 - 当你捕获时你总是返回。

具体做法是:

# We're in the caller now 
eval{ 
    local $SIG{__WARN__} = sub { 
     my $e = shift; 
     # log the error etc. 
     die MyWarnException->new("This is an exception."); 
    }; 

    # Offending statements go here 
    do_things(); 

}; 
if([email protected] && [email protected]>isa('MyWarnException')){ 
    return; 
} 
+0

所以,你的意思是,让处理程序设置一个全局标志,然后在后续代码中检查该标志是否被设置? – 2011-05-28 07:15:48

+0

其实我太匆忙纠正自己:你确实需要抛出异常。让我编辑答案以表明我的意思。 – trutheality 2011-05-28 07:30:58

0

你可以去死了()在你的处理器和捕捉这一个eval,如下图所示:

use 5.12.0; 

local $SIG{__WARN__} = sub { 
    my $e = shift; 
    # log the error etc. 
    die "$e"; 
}; 

func(undef); 
func('honk'); 

sub func { 
    my $foo = shift; 

    eval { 
     my $bar = "a $foo"; 
     say "$bar"; 
    }; 
    if ([email protected]) { 
     die [email protected] unless [email protected] =~ /^Use of uninitialized value/; 
    } 
    return; 
} 

你可能,不过,想如果警告直接检查可能发生并简单地返回:

sub func { 
    my $foo = shift; 
    return unless defined($foo); 
    ...; # use $foo fine 
} 
2

将两行分别包含在不同的函数中,首先返回一个表明调用函数应该返回的状态。根据需要,单独的函数可以处理警告 - 可能使用相同的函数来执行相同的日志记录。

sub wrap_line_1 
{ 
    local $SIG{__WARN__} = ...; 
    ...do line 1... 
    return ($warning_fired ? 1 : 0); 
} 

sub wrap_line_2 
{ 
    local $SIG{__WARN__} = ...; 
    ...do line 2... 
    return; 
} 


...calling code... 
wrap_line_1() and return; 
wrap_line_2(); 
... 
相关问题