Skip to content
This repository

Make errstate a decorator #270

Closed
wants to merge 1 commit into from

5 participants

Joonas Paalasmaa Charles Harris Nathaniel J. Smith Robert Kern
Joonas Paalasmaa

It would be very useful to be able to define floating point error handling per function. For example, you may know that a particular function triggers a harmless underflow (e.g. in computing probabilities), but you would like to keep error handling strict for other functions.

This patch implements a decorator interface to errstate.

Example:

import numpy

@numpy.errstate(invalid="warn")
def test_func1(a):
    numpy.sqrt(-1)

@numpy.errstate(invalid="raise")
def test_func2():
    numpy.sqrt(-1)

def main():
    test_func1(1)
    test_func2()

main()

Example output:

test_new_errstate.py:100: RuntimeWarning: invalid value encountered in sqrt
  numpy.sqrt(-1)
Traceback (most recent call last):
  File "test_new_errstate.py", line 110, in <module>
    main()
  File "test_new_errstate.py", line 108, in main
    test_func2()
  File "test_new_errstate.py", line 89, in func_with_error_handling
    return func(*args, **kwargs)
  File "test_new_errstate.py", line 104, in test_func2
    numpy.sqrt(-1)
FloatingPointError: invalid value encountered in sqrt
Charles Harris
Owner
charris commented

I like the idea, but we can't use functools until we drop support for 2.4. The same holds for the with statement. We will definitely move the supported version up at some point, perhaps after 1.7, but not yet.

Joonas Paalasmaa

What about making the decorator without functools?

Charles Harris
Owner
charris commented

Doing it without functools would be fine.

Nathaniel J. Smith
Owner
njsmith commented

Also, needs tests.

Charles Harris charris closed this
Charles Harris
Owner

ping the travisbot

Charles Harris charris reopened this
Joonas Paalasmaa

Now that the next release will drop Python 2.4 support, would it be possible to include this now (with a test, of course)?

Collaborator

Sounds good to me, also needs a rebase to merge.

Charles Harris
Owner

@jpaalasm Could you rebase this?

Charles Harris
Owner

Also needs documentation and a test.

Collaborator
seberg commented

Actually I randomly got wondering about it. Would it be more pure if this thing used a try: ... finally: ... block? Otherwise if the function errors it seems it might fail to reset the error state?

Collaborator
seberg commented

Oooops, nvm. it already uses the with statement :), completly missed that.

Nathaniel J. Smith
Owner

Now that I look, I'm... not at all a fan of this API. IMHO decorators should be used for things that are about "functions", i.e., generally API stuff. Functions shouldn't be treated as just a way to demarcate a chunk of code where you want something to happen -- that's what with and try/finally are for.

What advantage does

@np.errstate(...)
def f(...):
    ...

have over

def f(...):
    with np.errstate(...):
        ...

? It's not easier to read, it's less python-idiomatic, as a user of f I don't care about the errstate (it's an implementation detail) so having it in between me and the function declaration is confusing, and it's just adding a second way to do things for no purpose AFAICT (violating "there's only one way to do it").

Charles Harris
Owner

@njsmith I agree, actually ;)

OT, there are a lot of places in the code that could use this context manager now that support for 2.4 and 2.5 has been dropped. I didn't know it existed.

Robert Kern
Collaborator
rkern commented

@njsmith While I happen to agree with you in this case, this kind of thing is one of the reasons decorators were introduced to the language, so we shouldn't be too surprised that it gets proposed from time to time, especially when we were supporting 2.5. It just so happens that context managers showed up in the language later and are more (IMHO) fit for purpose. np.errstate() is already a context manager, so I agree that it should not grow decorator functionality as well.

@jpaalasm Thank you for your contribution! I think it made a lot of sense when you proposed it. With our dropping of pre-with-statement Pythons, though, I think that we should keep np.errstate() as it is.

Nathaniel J. Smith
Owner

Sounds like we have consensus then, so I'll close this.

@jpaalasm: Indeed, thanks for the contribution!

Nathaniel J. Smith njsmith closed this
Marten van Kerkwijk mhvk referenced this pull request in astropy/astropy
Open

Turn numpy warnings into exceptions #1588

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 1 unique commit by 1 author.

May 06, 2012
Joonas Paalasmaa jpaalasm Make errstate a decorator f3a3378
This page is out of date. Refresh to see the latest.

Showing 1 changed file with 11 additions and 0 deletions. Show diff stats Hide diff stats

  1. +11 0 numpy/core/numeric.py
11 numpy/core/numeric.py
@@ -24,6 +24,7 @@
24 24
25 25 import sys
26 26 import warnings
  27 +import functools
27 28 import multiarray
28 29 import umath
29 30 from umath import *
@@ -2604,15 +2605,25 @@ class errstate(object):
2604 2605 def __init__(self, **kwargs):
2605 2606 self.call = kwargs.pop('call',_Unspecified)
2606 2607 self.kwargs = kwargs
  2608 +
2607 2609 def __enter__(self):
2608 2610 self.oldstate = seterr(**self.kwargs)
2609 2611 if self.call is not _Unspecified:
2610 2612 self.oldcall = seterrcall(self.call)
  2613 +
2611 2614 def __exit__(self, *exc_info):
2612 2615 seterr(**self.oldstate)
2613 2616 if self.call is not _Unspecified:
2614 2617 seterrcall(self.oldcall)
2615 2618
  2619 + def __call__(self, func):
  2620 + @functools.wraps(func)
  2621 + def func_with_error_handling(*args, **kwargs):
  2622 + with self:
  2623 + return func(*args, **kwargs)
  2624 +
  2625 + return func_with_error_handling
  2626 +
2616 2627 def _setdef():
2617 2628 defval = [UFUNC_BUFSIZE_DEFAULT, ERR_DEFAULT2, None]
2618 2629 umath.seterrobj(defval)

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.