[Python-Dev] Acquire/release functionality

Michael Hudson mwh@python.net
Mon, 03 Feb 2003 12:12:01 +0000


Paul Moore <lists@morpheus.demon.co.uk> writes:

> As far as the acquire/release case is concerned, I think that there is
> definitely a strong case for syntactic support for this. The
> equivalent idiom in C++ is "resource acquisition is initialisation"
> which, while not having syntax support, does rely on the existence of
> deterministic destructors, and on the ability to introduce a new scope
> at will. Python has neither of these, and the try...finally construct
> is verbose enough to make something better worth having.

I like this.

> On the other hand, the simple "with" construct proposed by Samuele
>
>> with <expr>:
>>  <suite>
>>
>> would be possibly sugar for:
>
> [...]
>
>> _x = <expr>
>> _x.__enter__()
>> try:
>>   try:
>>    <suite>
>>   except  getattr(_x,'__excepts__',()),_e:
>>     _x.__except__(_e)
>> finally:
>>   _x.__exit__()
>
> extended as suggested by Alex to allow __enter__ to be optional and to
> allow for an assignment in the with statement, seems to cover this
> excellently.

Making the methods optional seems reasonable but writing do-nothing
methods isn't much of a strain.  I don't care either way.

> (I'm not sure the exception handling needs to be quite
> that complex, but that's a minor point).

I'm not at all sure.  In fact, on thinking about it I feel it may be a
bad idea.  Examples of when __except__ might be different from
__exit__ would be appreciated.

[....]
> So, to offer a unified proposal, I'd suggest the following syntax:
>
> with [ var1 [, var2, ... ] = ] expr1 [, expr2 , ... ]:
>     suite
> 
> This is equivalent to
>
> var1, var2, ... = expr1, expr2, ...
>
> if hasattr(var1, "__enter__"):
>     var1.__enter__()
> if hasattr(var2, "__enter__"):
>     var2.__enter__()
> ...
>
> try:
>     try:
>         suite
>
>     except:
>         # Handwave here for now
>
> finally:
>     ...
>     var2.__exit__()
>     var1.__exit__()

I think this might be unnecessarily hard to compile.

class multimonitor(object):
    def __init__(self, monitors):
        self.monitors = monitors
    def __enter__(self):
        for monitor in self.monitors:
            monitor.__enter__()
    def __exit__(self):
        for monitor in self.monitors:
            monitor.__exit__()

It should probably be stated that an __exit__ method should never
raise an exception.

> In this, any varN can be omitted and a dummy hidden variable is
> used. 

Persuading the parser to distinguish 

with foo():

and 

with var = foo():

is going to be tricky.  I think we'll have to settle for one or the
other.

> The handwaving around the except clause needs to be clarified - what
> I want is to call varN.__except__() ... var1.__except__() allowing
> each in turn to catch the exception.

This sort of problem is an argument for throwing away the except:
clause.

> The __except__ attribute should be optional, as well. I can't see any
> reason why it would ever be useful for __exit__ to be optional, but
> for generality it might be worth allowing that as well.

Hmm.  Maybe.  Not fond of generality for the sake of it.

> I like "with" as the keyword here. One obvious question - if we decide
> to go with syntax like this, would we be looking at "pre-reserving"
> the keyword in Python 2.3 somehow, so that it could become a full
> keyword in 2.4? Or would the new syntax need a future statement in
> Python 2.4, to become finalised in 2.5?

I think nothing should change in 2.3.

> PS Just to summarise things once more: as I see it, we now have a
>    number of threads lurking:
>
>    - The def f(arg) [...] syntax that started all this off
>    - With blocks (which give us acquire/release) for which I propose a
>      unified solution above

I'll write PEPs for these two in due course if noone beats me to it.

>    - Properties, which don't have a specific solution proposed yet
>      (AFAICT)
>    - Thunks in various forms, most notably Guido's hyper-general
>      version (the one that lets us implement switch)
>
>    It's not at all clear to me that the thunk based solutions have
>    killer use cases that they solve better than anything else
>    (assuming that switch doesn't count :-)) but they may be aiming at
>    the property case. If so, I'd appreciate a concrete "this is how
>    we'd write a property" explanation, as I'm losing the plot on
>    that... 

Me too.  Guido can do this PEP :-)

[...]
>    I'll stop now before I feel a need to summarise the summary of my
>    summary :-)

OK, I cheated with the sig :-)

Cheers,
M.

-- 
  To summarise the summary of the summary:- people are a problem.
                   -- The Hitch-Hikers Guide to the Galaxy, Episode 12