K
Klaas
Occasionally I find myself wanting a block that I can break out of at
arbitrary depth--like java's named break statements. Exceptions can
obviously be used for this, but it doesn't always look nice.
The with statement can be used to whip up something quite usable:
class ExitBlock(object):
""" A context manager that can be broken out of at an arbitrary
depth,
using .exit() """
def __init__(self):
class UniqueException(BaseException):
pass
self.breakExc = UniqueException
def exit(self):
raise self.breakExc()
def __enter__(self):
return self
def __exit__(self, t, v, tb):
return t is self.breakExc
Now the most important thing here is that each exit block creates a
unique exception type. If you have philosophical issues with creates
unboundedly many type objects, you can use unique instances too.
This allows named break-out-able blocks:
with ExitBlock() as ex1:
with ExitBlock() as ex2:
with ExitBlock() as ex3:
while True:
ex2.exit()
print 'not displayed'
print 'execution proceeds here from ex2.exit()'
while True:
for x in xrange(sys.maxint):
while True:
ex1.exit()
print 'not displayed'
print 'execution proceeds here from ex1.exit()'
The only danger is bare except (or except BaseException) inside the
block.
-Mike
arbitrary depth--like java's named break statements. Exceptions can
obviously be used for this, but it doesn't always look nice.
The with statement can be used to whip up something quite usable:
class ExitBlock(object):
""" A context manager that can be broken out of at an arbitrary
depth,
using .exit() """
def __init__(self):
class UniqueException(BaseException):
pass
self.breakExc = UniqueException
def exit(self):
raise self.breakExc()
def __enter__(self):
return self
def __exit__(self, t, v, tb):
return t is self.breakExc
Now the most important thing here is that each exit block creates a
unique exception type. If you have philosophical issues with creates
unboundedly many type objects, you can use unique instances too.
This allows named break-out-able blocks:
with ExitBlock() as ex1:
with ExitBlock() as ex2:
with ExitBlock() as ex3:
while True:
ex2.exit()
print 'not displayed'
print 'execution proceeds here from ex2.exit()'
while True:
for x in xrange(sys.maxint):
while True:
ex1.exit()
print 'not displayed'
print 'execution proceeds here from ex1.exit()'
The only danger is bare except (or except BaseException) inside the
block.
-Mike