Bengt Richter bokr at
Fri Jul 25 23:57:44 CEST 2003

On 25 Jul 2003 13:35:49 -0700, Paul Rubin <> wrote:

>bokr at (Bengt Richter) writes:
>> >"done" here is a generic method that gets called on exiting a "with"
>> >block.  
>> First reaction == +1, but some questions...
>> 1) Is f.done() really necessary? I.e., doesn't an explicit del f
>>    take care of it if the object has been coded with a __del__
>>    method? I.e., the idea was to get the effect of CPython's
>>    immediate effective del on ref count going to zero, right?
>The ref count might not be zero.  Something inside the "with" block
>might make a new reference and leave it around.
Aha. In that case, is the del just a courtesy default action?

>> 2) how about with two files (or other multiple resources)?
>>     with f1,f2 = file('f1'), file('f2'):
>>         [do stuff with f1 & f2]
>> What is the canonical expansion?
>I think f1.done and f2.done should both get called.
Consistently ;-)

>> Also, what about the attribute version, i.e.,
>>     ob.f = file(frob)
>>     try:
>>       [do stuff with ob.f]
>>     finally:
>>       del ob.f # calls f.__del__, which calls/does f.close()
>> I.e., ob.f = something could raise an exception (e.g., a read-only property)
>> *after* file(frob) has succeeded. So I guess the easiest would be to limit
>> the left hand side to plain names... 
>The assignment should be inside the try.  If I had it on the outside
>before, that was an error.

Really? Don't you want a failing f = file(frob) exception to skip the finally,
since f might not even be bound to anything in that case?

The trouble I was pointing to is having two possible causes for exception, and only
one of them being of relevance to the file resource.

Maybe if you wanted to go to the trouble, it could be split something like

    with ob.f = file(frob):
        [do stuff with ob.f]


    _tmp = file(frob)
        ob.f = _tmp
        [ do stuff with ob.f ]
        del _tmp
        del ob.f

Not sure about the order. Plain ob.f.done() would not guarantee a call to _tmp.done(),
since ob could refuse to produce f, and f could be a wrapper produced during ob.f = _tmp,
and it might not have a __del__ method etc etc. _tmp is just for some internal temp binding.

Bengt Richter

More information about the Python-list mailing list