A "scopeguard" for Python
Alf P. Steinbach
alfps at start.no
Thu Mar 4 17:27:03 EST 2010
* Mike Kent:
> On Mar 4, 12:30 pm, Robert Kern <robert.k... at gmail.com> wrote:
>
>> He's ignorant of the use cases of the with: statement, true.
>
> <humor> Ouch! Ignorant of the use cases of the with statement, am I?
> Odd, I use it all the time. </humor>
>
>> Given only your
>> example of the with: statement, it is hard to fault him for thinking that try:
>> finally: wouldn't suffice.
>
> <humor> Damn me with faint praise, will you? </humor>
>
> I'm kinda amazed at the drama my innocent request for the use case
> elicited. From what I've gotten so far from this thread, for the
> actual example Mr. Steinbach used, the only disadvantage to my counter-
> example using try/finally is that the chdir in the finally part will
> always be executed, even if the chdir in the try part did not
> succeed. I concede that, and was aware of it when I wrote it. For
> the simple example given, I did not consider it compelling.
Uhm, well.
My example was:
with Cleanup as at_cleanup:
# blah blah
chdir( somewhere )
at_cleanup.call( lambda: chdir( original_dir ) )
# blah blah
It was not intended to compel, rather just to illustrate usage. :-)
And you asked about comparing that with ...
original_dir = os.getcwd()
try:
os.chdir(somewhere)
# Do other stuff
finally:
os.chdir(original_dir)
# Do other cleanup
.. which does something different, namely, always executing the
os.chdir(original_dir) or more generally the action-specific cleanup.
The action-specific cleanup might be much more costly than a chdir, and/or, in
the case where the action failed, incorrect.
In the same number of lines and with fewer keystrokes you could have written
code that was equivalent to the code I posted and that you wanted to compare
with, e.g. ...
original_dir = os.getcwd()
os.chdir(somewhere)
try:
# Do other stuff
finally:
os.chdir(original_dir)
# Do other cleanup
... so given how easy it is to write such an equivalent code snippet, I assumed
that the different behavior was /not/ intended, that instead, you'd attempted to
write equivalent code but made a slight error in the translation to lower level
construct -- but impossible to say exactly what.
Now you write that you were "aware of [the different behavior] when I wrote it",
and that just baffles me: why not then, as a basis of sound comparision, write
the equivalent code shown above, the same number of lines as what you wrote?
> A more
> complex example, that would have required multiple, nested try/finally
> blocks, would show the advantages of Mr Steinbach's recipe more
> clearly.
>
> However, I fail to understand his response that I must have meant try/
> else instead, as this, as Mr. Kern pointed out, is invalid syntax.
> Perhaps Mr. Steinbach would like to give an example?
OK.
Assuming that you wanted the chdir to be within a try block (which it was in
your code), then to get code equivalent to my code, for the purpose of a
comparision of codes that do the same, you'd have to write something like ...
original_dir = os.getcwd()
try:
os.chdir(somewhere)
except Whatever:
# E.g. log it.
raise
else:
try:
# Do other stuff
finally:
os.chdir(original_dir)
# Do other cleanup
... which would be a more general case.
I've also given this example in response to Robert earlier in the thread.
Although I haven't tried it I believe it's syntactically valid. If not, then the
relevant typo should just be fixed. :-)
I have no idea which construct Robert thought was syntactically invalid. I think
that if he's written that, then it must have been something he thought of.
Cheers & hth.,
- Alf
More information about the Python-list
mailing list