3

I am trying to create generic exception handler - for where I can set an arg to return in case of exception, inspired from this answer.

import contextlib


@contextlib.contextmanager
def handler(default):
    try:
        yield
    except Exception as e:
        yield default


def main():
    with handler(0):
        return 1 / 0

    with handler(0):
        return 100 / 0

    with handler(0):
        return 'helllo + 'cheese'

But this results in

RuntimeError: generator didn't stop after throw()
Community
  • 1
  • 1
Rich Tier
  • 9,021
  • 10
  • 48
  • 71

1 Answers1

3

The main conceptual problem is that you try to make the calling function implicitly return a value from within a called function. To give an example, what you are trying to do is coneptually equivalent to this situation:

def f():
    # some magic code here

def g():
    f()

And now you want the magic code to make g() return some value. This is never going to work.

Context managers are the wrong tool for this purpose. Consider using a decorator instead.

Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
  • @JonClements: OK, I should be more specific. By "this is never going to work" I mean "you're never going to make those `with` blocks work in the way you intend". Of course you can write a wrapper function, but I'd suggest to use a decorator instead. – Sven Marnach Nov 03 '12 at 23:20
  • I don't think that is correct. The real reason is that this decorator requires a generator that yields only one value. This one yields two values, thus is not "stopped" at the end, as the error says. – Keith Nov 03 '12 at 23:31
  • 1
    @rikAtee Umm no - pretend that code doesn't exist! The correct way is pdysigner's answer per your follow up question: http://stackoverflow.com/questions/13214377/generic-exception-handling-return-value – Jon Clements Nov 03 '12 at 23:31
  • @Keith: My answer gives a reason why a context manager can't do what the OP is trying to do. It indeed does not answer how exactly the error message comes about, since I felt some general advice is more useful here. Feel free to add your own answer with explanations of the error. – Sven Marnach Nov 04 '12 at 00:01