On Nov 19, 2019, at 17:57, Oscar Benjamin <oscar.j.benja...@gmail.com> wrote:
> 
> 
> Perhaps a less emotive way of distinguishing these classes of context
> managers would be as "eager" vs "lazy". An eager context manager jumps
> the gun and does whatever needs undoing or following up before its
> __enter__ method is called. A lazy context manager waits until
> __enter__ is called before committing itself.
> 
> I don't really want to give a sense of equality between eager and lazy
> though. To me it is clear that lazy context managers are preferable.

What you’re calling “lazy” context managers are better in that they work with 
tools like nested.

But “eager” context managers are better in that they can be used as resources 
when the context manager protocol doesn’t help, as when the releasing doesn’t 
happen in the same lexical scope as the acquiring. (Go back to my example with 
someone who opens a file, and then opens another file if that didn’t raise, to 
see why you can’t just use a lazy context manager anyway.)

You can go back and forth arguing that the first one is more important or that 
the second one is more important, but neither argument rebuts the fact that the 
other kind actually does have benefits.

So, where do you go from there?

Option 1 is to assume that context managers are, or can be, eager, and 
therefore tools like nested are bug magnets and can’t be put somewhere as 
prominent as contextlib. That’s where we are today, and you don’t like it.

Option 2 is to assume that context managers are lazy (maybe with some rare 
exceptions but those should be clearly called out), so file object and SQLite 
connections and dozens of other context managers, stdlib and third party, all 
need to be fixed. That’s what you’re suggesting, but I doubt it’s ever going to 
happen.

Is there a third option? Maybe. If we accept that both exist, we just need some 
way to distinguish the two, and to make tools like nested raise if fed an eager 
one, right? That sounds like a job for an ABC—one that classes have to manually 
opt in to via inheritance or registration, but a bunch of the stuff in 
contextlib (including the wrapper around generator functions) that people use 
directly or use to create their own context managers is definitely lazy and 
would opt in. 

You can also create either a generic wrapper that wraps any eager context 
manager factory into a lazy one, or create specific lazy context managers or cm 
factories like opening, or both.

You can also do the reverse wrapper, and use that to try to convince people to 
always write their context managers lazy and wrap if they need an eager one.

Submit all of this to contextlib2 (or, if Nick rejects it, create your own PyPI 
project instead) and see if people use it. If so, you can propose merging it 
all into the stdlib, and maybe even shortcuts like making tuples act like 
nested.

In the long run, you can start pressuring people to write their tutorials and 
blog posts and python-list and StackOverflow answers to favor creating and 
using lazy context managers whenever possible (“because they work with the 
tuple syntax” seems like a good argument…).

And you can do all of this without needing to change the protocol.
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/N4NJIA4XE6NDBKCQLQYIFYZY5IKT37L2/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to