A "scopeguard" for Python

Steve Howell showell30 at yahoo.com
Fri Mar 5 17:38:27 CET 2010


On Mar 5, 8:29 am, Mike Kent <mrmak... at gmail.com> wrote:
> On Mar 4, 8:04 pm, Robert Kern <robert.k... at 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.




More information about the Python-list mailing list