[Numpy-discussion] numpy error handling

Tim Hochberg tim.hochberg at cox.net
Fri Mar 31 18:38:07 CST 2006


I've just been looking at how numpy handles changing the behaviour that 
is triggered when there are numeric error conditions (overflow, 
underflow, etc.). If I understand it correctly, and that's a big if, I 
don't think I like it nearly as much as the what numarray has in place.

It appears that numpy uses the two functions, seterr and geterr, to set 
and query the error handling. These set/read a secret variable stored in 
the local scope. I assume that the various ufuncs then examine that 
value to determine how to handle errors. The secret variable approach is 
a little clunky, but that's not what concerns me. What concerns me is 
that this approach is *only* useful for built in numpy functions and 
falls down if we call any user defined functions.

Suppose we want to be warned on underflow. Setting this is as simple as:

    def func(*args):
        numpy.seterr(under='warn')
        # do stuff with args
        return result

Since seterr is local to the function, we don't have to reset the error 
handling at the end, which is convenient. And, this works fine if all we 
are doing is calling numpy functions and methods. However, if we are 
calling a function of our own devising we're out of luck since the 
called function will not inherit the error settings that we have set. 
Thus we have no way to influence the error settings of functions 
downstream from us.

Compare this to the numarray approach, where you write code like the 
following:

    def func(*args)
        numarray.Error.pushMode(underflow='warn')
        try:
           # do stuff with args
           return result
        finally:
           numarray.Error.popMode()

At first glance this looks a lot more clunky. However, it's also a lot 
more useful. In this case, pushMode pushes a new error mode value onto a 
global[1] stack of mode values. Thus, any functions that func calls, 
will inherit it's error settings, unless they explicitly override them. 
As for the clunkiness factor, that's partly just the choice of camelCase 
versus smashwords, but also the try-finally. The second, however, will 
be addressed in Python 2.5 with the 'with' statement. At that point, we 
could have a numpy equivalent to the above numarray code that looked 
something like:

    def func(*args)
        with numpy.errors(underflow='warn'):
           # do stuff with args
           return result

I believe we should rework the error handling to follow the numarray 
model before things get set in stone at 1.0. The 'with' statement 
support can be worked in a bit later if need be, although I suspect that 
will be easy.

I also would prefer more verbose keys ala numarray (underflow, overflow, 
dicidebyzero and invalid) than those currently used by numpy (under, 
over, divide and invalid). And (will he never stop) I like numarrays 
defaults better here too: overflow='warn', underflow='ignore', 
dividebyzero='warn', invalid='warn'. Currently, numpy defaults to ignore 
for all cases. These last points are relatively minor though.

Regards,

-tim


[1] I believe it's actually thread local, and if it's not it should be, 
but that detail is not important for our discussion here.





More information about the Numpy-discussion mailing list