开发者

Returning error messages from perl subroutines

Is this a good way of returning an error messages from a subroutine in perl?

sub some_subroutine{
    # do something
    $something = 14;

    if(1 == 2){
        $_ = "This should not be hap开发者_如何学编程pening!";
        return undef;
    }
    return $something;
}

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

The code runs OK (in a parallel world, where 1 == 2), but using $_ to return the error message is a good way? I didn't found any documentation regarding the usage of $_ for this kind of purposes.

Thank you!


$_ is not a good mechanism as so many other things use and set it.

You could set some other global variable, like $Error, but the best way is to throw an exception. Then the user doesn't have to always check, and forget, it just happens. In Perl, exceptions are generated with "die". die will take a string or an object. There's a number of modules to make throwing exceptions easier including Exception::Class, Exception::Simple, Ouch and autodie.

You can catch the exception with eval {}, but there are a number of problems with that so you should use something like Try::Tiny.


It's not unknown to use a global variable to hold the error message. For example, built-in function use $!, and DBI uses $DBI::errstr. But then you inherit all the problems of using global variables. Signal handlers need to localise them, destructors can clobber them, multi-threading issues, etc.

It seems to me that throwing an exception (e.g. using die) is a more common choice.

Whatever you do, don't use $_. It is often aliased to something, so using it could have unintended consequences.


One thing you can do to make this slightly better is to simply return; on error/undefined result. There are contexts where return undef; can be evaluated as true. You might check out Perl Best Practices's chapter on error handling as it covers this and has other good pointers.

For example, if:

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

becomes

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

You have a weird bug (not catching the error) that may be hard to track down, whereas if you return; from some_subroutine you get:

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

Furthermore, in the case of a function that should return a list:

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

So, while there are other patterns for returning error/undefined status from a function, always using return; allows the use of one pattern for nearly all functions, both in returning the appropriate value and when it comes time to check for error status.


It totally depends on what behavior you are expecting to see from your error handler. It is very common in perl to use die or warn in case a runtime error/warning happens.

Take a look at this tutorial on error handling in perl: http://www.tutorialspoint.com/perl/perl_error_handeling.htm


For a web service, you could write a subroutine for printing custom error responses (40x errors, etc.).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜