[Python-Dev] Merging PEP 310 and PEP 340-redux?

Phillip J. Eby pje at telecommunity.com
Tue May 10 18:58:36 CEST 2005


At 08:51 AM 5/10/2005 -0700, Guido van Rossum wrote:
>[Phillip J. Eby]
> > Yeah, I'd ideally like to see __try__, __except__, __else__, and
> > __finally__ methods, matching the respective semantics of those clauses in
> > a try/except/finally block.
>
>What's your use case for adding this complexity?

It makes it much easier to mentally translate a given 
try/except/else/finally usage to a "resource" or "block controller" or 
whatever it is we're calling these things now.  You should almost be able 
to just stick 'def __' and '__(self):' and then munge the whole thing into 
a class.

Of course, it's not *really* that simple, because __try__ doesn't exactly 
correspond to 'try:', and it has to return something, but it sure is 
simpler than the mental gymnastics I'd go through to convert 
except/else/finally into "if" statements inside an __exit__.

Granted, if we end up with __enter__ and __exit__, I'll just write a 
resource mixin class whose __exit__ calls a stubbed-out __except__, 
__else__, and __finally__.  Then I won't have to figure out how to write 
__exit__ methods all the time.  Which is great for me, but I was thinking 
that this interface would reduce complexity for people trying to learn how 
to write these things.

I wasn't advocating this before because PEP 340's use of generators allowed 
you to directly use try/except/else/finally.  But, the new approach seems 
targeted at a wider set of use cases that don't include generators.  IOW, 
it's likely you'll be adding resource-finalization methods to actual 
resource classes, and grafting generators into them to implement 
__enter__/__exit__ seems more complex at first glance than just letting 
people add the methods directly; e.g.:

     def __enter__(self):
         self.handler = self._resource_control()
         return self.handler.__enter__()

     def __exit__(self):
         self.handler.__exit__()

     @with_template
     def _resource_control(self):
         f = self.open("blah")
         try:
             yield f
         finally:
             f.close()

versus this rather more "obvious way" to do it:

     def __try__(self):
         self.f = self.open("blah")
         return self.f

     def __finally__(self):
         self.f.close()

But I suppose you could encapsulate either pattern as a mixin class, so I 
suppose this could be treated as a matter for examples in documentation 
rather than as an implementation aspect.  It's just that if __exit__ has to 
probe exception state or other wizardry, it's going to be harder for 
non-wizards to use, and that's what I was reacting to here.   Anyway, I see 
now that documentation and simple mixins could address it, so if you think 
it's best handled that way, so be it.


>  I'm going for simple
>here unless there's a really strong use case. Anyway, a wrapped
>generator wrapper can't do with all those distinctions unless we
>augment the generator somehow ("continue EXPR" would suffice).

You'd use only __try__, __except__, and __else__ to wrap a generator.  For 
some other use cases you'd only use __try__ and __finally__, or __try__ and 
__except__, or __try__ and __else__.  I don't know of any use cases where 
you'd want to use all four simultaneously on the same controller.


>(Your decorator is equivalent to mine, but I don't like creating a new
>class each time.)

Mine was just a sketch to show the idea anyway; I'd be surprised if it 
doesn't have at least one bug.



More information about the Python-Dev mailing list