On Mar 5, 8:29 am, Mike Kent <mrmak...@gmail.com> wrote: > On Mar 4, 8:04 pm, Robert Kern <robert.k...@gmail.com> wrote: > > > No, the try: finally: is not implicit. See the source for > > contextlib.GeneratorContextManager. When __exit__() gets an exception from > > the > > with: block, it will push it into the generator using its .throw() method. > > This > > raises the exception inside the generator at the yield statement. > > Wow, I just learned something new. My understanding of context > managers was that the __exit__ method was guaranteed to be executed > regardless of how the context was left. I have often written my own > context manager classes, giving them the __enter__ and __exit__ > methods. I had mistakenly assumed that the @contextmanager decorator > turned a generator function into a context manager with the same > behavior as the equivalent context manager class. Now I learn that, > no, in order to have the 'undo' code executed in the presence of an > exception, you must write your own try/finally block in the generator > function. > > This raises the question in my mind: What's the use case for using > @contextmanager rather than wrapping your code in a context manager > class that defines __enter__ and __exit__, if you still have to > manager your own try/finally block?
Unless I am misunderstanding the question, the use case is that you still only have to write the context manager once, and you might get multiple uses out of it where the with-enclosed code blocks work at a higher level of abstraction. I actually don't use @contextmanager yet, mainly because I did not know it existed until recently, but also because I find the __enter__/ __exit__ paradigm straightforward enough to just hand code them that way. -- http://mail.python.org/mailman/listinfo/python-list