2011-04-14 63 views
13

这是从perl中的子例程返回错误消息的好方法吗?从Perl子程序返回错误消息

sub some_subroutine{ 
    # do something 
    $something = 14; 

    if(1 == 2){ 
     $_ = "This should not be happening!"; 
     return undef; 
    } 
    return $something; 
} 

my $ret=some_subroutine(); 
print "ERROR: $_" unless(defined $ret); 

的代码运行正常(在一个平行的世界,在那里1 == 2),但使用$_返回的错误信息是一个好办法?我没有发现任何关于$_用于这种目的的文档。

谢谢!

回答

22

$_是不是一个很好的机制,许多其他的事情使用和设置它。

您可以设置一些其他全局变量,如$ Error,但最好的方法是引发异常。然后用户不必总是检查,忘记,它只是发生。在Perl中,异常由“die”生成。死亡将采取一个字符串或一个对象。有许多模块可以使投掷异常更容易,包括Exception::Class,Exception::Simple,Ouchautodie

你可以用eval {}来发现异常,但有a number of problems with that,所以你应该使用类似Try::Tiny的东西。

+0

当错误不是“例外吗?”时,您是否觉得它在语义上有价值返回错误/未定义状态?如果你期待的是,一个文件可能不在那里,那么在语义上是不是更有意义的返回错误状态而不是抛出异常?这是一个小问题,我知道...... – wprl 2011-04-18 21:59:23

+3

@SoloBold不要因为“异常”的确切含义而太受伤。如果子程序不能完成它的工作,这是一个特例。如果这意味着调用者无法期望正常的返回值,那么这是一个特例。如果你编写一个检查文件存在的子程序,那么它不在那里是不例外的。如果你编写一个读取和解析文件的例程,它应该会在文件不存在时抛出异常。 – Schwern 2011-04-19 11:37:00

+4

...如果较大的系统没有找到那个文件,你可以在这个文件中加上一个包装来检查文件是否存在,如果没有则返回空的结构。最后,程序员会忘记编写错误处理代码,但你必须故意忽略一个异常。它针对懒惰进行了优化。 – Schwern 2011-04-19 11:39:09

1

这完全取决于您期望从错误处理程序中看到的行为。在发生运行时错误/警告的情况下,使用diewarn在perl中很常见。

在本教程中采取的错误在Perl处理一看:http://www.tutorialspoint.com/perl/perl_error_handeling.htm

+3

这真的不是一个很好的错误处理教程。 – 2011-04-18 14:49:25

7

使用全局变量来保存错误消息并不是未知数。例如,内置函数使用$!,而DBI使用$DBI::errstr。但是,你继承了使用全局变量的所有问题。信号处理程序需要对它们进行本地化,破坏程序可以摧毁它们,多线程问题等。

在我看来,引发异常(例如使用die)是更常见的选择。

无论你做什么,都不要使用$_。它往往是别名,所以使用它可能会产生意想不到的后果。

0

对于Web服务,您可以编写用于打印自定义错误响应(40x错误等)的子例程。

2

有一两件事你可以做,使这稍微好一点的是简单地在错误/未定义的结果return;。有些情况下return undef;可以评估为true。你可以看看Perl Best Practices关于错误处理的章节,因为它涵盖了这一点,并且有其他好的指针。

例如,如果:

my $ret=some_subroutine(); 
print "ERROR: $_" unless(defined $ret); 

成为

my @ret=some_subroutine();   # oops! 
print "ERROR: $_" unless(defined $ret); 

你有一个奇怪的问题(不是捕捉错误),可能很难追查,而如果你return;some_subroutine你得到:

my @ret=some_subroutine();   # oops! 
print "ERROR: $_" unless($ret); # but error is still caught 

此外,在函数t帽子应该返回一个列表:

my @ret=some_other_subroutine(); # OK 
print "ERROR: $_" unless($ret);  # error will be caught if you "return;" 

# ... but later ... 

my $ret=some_other_subroutine(); # oops! 
print "ERROR: $_" unless($ret);  # if you "return;" $ret will equal 0 
            # (the length of the returned list) 
            # and the error will be caught 

所以,虽然也有其他模式用于从函数返回的错误/妾身,总是使用return;允许使用一个模式的几乎所有功能,无论是在返回适当的值以及何时需要检查错误状态。

+4

这是PBP中不良建议的一个例子。如果一个子例程通常返回一个标量,则在返回undef时出错,而不是空列表。 – ysth 2011-04-15 05:22:51

+0

这很有趣,但你没有说服我。如果函数在列表上下文中被调用,返回一个元素列表'(undef)'似乎同样不好。子例程可能会返回一个标量,但是如果从列表上下文中调用它,如果我理解正确,则不会得到标量。您可以始终确保!foo()在您返回时为true;'但不在返回undef时为' – wprl 2011-04-15 17:22:27

+0

http://stackoverflow.com/questions/3435122/whats-the-difference-between-return -and-return-undef-in-perl – wprl 2011-04-15 17:23:36