On Sat, 30 May 2009 10:30:40 +1000 Steven D'Aprano firstname.lastname@example.org wrote:
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.