On Sat, 30 May 2009 10:30:40 +1000
Steven D'Aprano
and if for some bizarre reason you want to catch errors in the context manager but not the body of with, you can manually emulate with:
# untested try: try: f = open(filename).__enter__() except Exception: f = None process(f) finally: if f is not None: f.__exit__()
That fourth case is ugly, but it's also rare. I can't imagine a case where you'd need it, but if you do, you can do it.
That was the case that first drove me to think about extending
with. The starting point was a loop:
while retries < maxretries:
try:
with my_magic_lock:
process()
except ProcessException:
handle()
except:
pass
retries += 1
If entering my_magic_lock throws an exception, I don't care - I'm
going to retry it anyway. We encountered a condition that caused
my_magic_lock to throw ProcessException, so handle() would run without
the lock and potentially corrupt our data. Extending with and wanting
a way to throw an except *over* the first surrounding try:/except:
both occurred to me. What I eventually did was push the loop into a
wrapper context manager.