Break or exit out of “with” statement?

with giving you trouble? Throw more with-able objects at the problem!

class fragile(object):
    class Break(Exception):
      """Break out of the with statement"""

    def __init__(self, value):
        self.value = value

    def __enter__(self):
        return self.value.__enter__()

    def __exit__(self, etype, value, traceback):
        error = self.value.__exit__(etype, value, traceback)
        if etype == self.Break:
            return True
        return error

Just wrap the expression you’re going to with with fragile, and raise fragile.Break to break out at any point!

with fragile(open(path)) as f:
    print 'before condition'
    if condition:
        raise fragile.Break
    print 'after condition'

Benefits of this setup

  • Uses with and just the with; doesn’t wrap your function in a semantically misleading one-run ‘loop’ or a narrowly specialized function, and doesn’t force you to do any extra error handling after the with.
  • Keeps your local variables available, instead of having to pass them to a wrapping function.
  • Nestable!

    with fragile(open(path1)) as f:
        with fragile(open(path2)) as g:
            print f.read()
            print g.read()
            raise fragile.Break
            print "This wont happen"
        print "This will though!"
    

    This way, you don’t have to create a new function to wrap the outer with if you want both to break.

  • Doesn’t require restructuring at all: just wrap what you already have with fragile and you’re good to go!

Downsides of this setup

  • Doesn’t actually use a ‘break’ statement. Can’t win em all 😉

Leave a Comment