On Sun, Apr 7, 2013 at 6:40 PM, Barrett Lewis <musikal.fus...@gmail.com> wrote: > I was recently watching that Raymond Hettinger video on creating Beautiful > Python from this years PyCon. > He mentioned pushing up the new idiom > > with ignored(<ignored_exceptions>): > # do some work > > I tracked down his commit here http://hg.python.org/cpython/rev/406b47c64480 > > But am unsure how the yield works in the given situation. > > I know about creating generators with yield and have read the docs on how it > maintains state. > > I think it works because it is returning control back to the caller while > maintaining the try so if the caller throws it is caught by the context. Is > this correct? I would love an in depth explanation of how this is working. I > am trying to learn as much as possible about the actual python internals.
The first thing to understand is that ignored() is a context manager and how context managers work. A context manager is an object with an __enter__ method and an __exit__ method. For example, the ignored() context manager could have been written as: class ignored: def __init__(self, *exceptions): self.__exceptions = exceptions def __enter__(self): return def __exit__(self, exc_type, exc_value, traceback): if exc_type is not None: return issubclass(exc_type, self.__exceptions) The __enter__ method is called when the with block is entered and sets up the context. The __exit__ method is called when the with block is exited and is passed the exception if one was raised. It returns True to suppress the exception, or False to continue propagating it. However, ignored() is actually implemented as a generator function with the @contextmanager decorator shortcut. This decorator takes a generator function and wraps it up as a class with the necessary __enter__ and __exit__ methods. The __enter__ method in this case calls the .next() method of the generator and returns after it yields once. The __exit__ method calls it again -- or it calls the .throw() method if an exception was passed in -- and expects the generator to exit as a result. So from the perspective of the generator it does its context setup (in this case, setting up a try block) prior to the yield, and then does the cleanup (in this case, selectively catching and suppressing the exceptions) after the yield. -- http://mail.python.org/mailman/listinfo/python-list