[Python-ideas] Generator-based context managers can't skip __exit__

Ram Rachum ram at rachum.com
Sun Nov 6 02:18:14 EST 2016


On Sun, Nov 6, 2016 at 8:53 AM, Nick Coghlan <ncoghlan at gmail.com> wrote:

> On 6 November 2016 at 16:07, Ram Rachum <ram at rachum.com> wrote:
> > Heh, I just played with this, and found a workaround. If I do something
> like
> > this after creating the generator:
> >
> > sys.g = g
> >
> > Then it wouldn't get closed when Python finishes, and the cleanup won't
> > happen, which is what I want.
>
> The interpreter goes to significant lengths to make sure that finally
> clauses get executed prior to or during interpreter shutdown, and any
> means you find by which they don't get executed is considered a bug
> (not always a fixable bug, but a bug nonetheless). If you rely on
> those bugs and limitations to get your program to perform the way you
> want it to you're going to run into problems later when upgrading to
> new CPython versions, or trying out different interpreter
> implementations.
>

I understand, and I agree with the reasoning. Still, I think I'll take my
chances.

There's still something seriously odd going in relation to your
> overall resource management architecture if "cleanup, maybe, unless I
> decide to tell you not to" is a behaviour you regularly need. Cleanup
> functions in a garbage collected environment should be idempotent, so
> it doesn't matter if you redundantly call them again later.
>

Well, you think it's weird that I want a `finally` clause to not be called
in some circumstances. Do you think it's equally weird to want an
`__exit__` method that is not called in some circumstances?


>
> However, if you *do* need that pattern regularly, then the pattern
> itself can be encapsulated in a context manager:
>
>     class callback_unless_exit:
>         def __init__(self, callback):
>             self.callback = callback
>         def __enter__(self):
>             return self
>         def __exit__(self, exc_type, exc_value, exc_tb):
>             if issubclass(exc_type, GeneratorExit):
>                 return
>             self.callback()
>
> and then do:
>
>     with callback_unless_exit(cleanup):
>         yield
>
> in the context managers where you want that behaviour.
>
>
Thanks for the workaround but I feel it's even less elegant than my
original workaround.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20161106/c49d11ab/attachment.html>


More information about the Python-ideas mailing list