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.