[Python-Dev] exec/with thunk-handling proposal
Michael Hudson
mwh@python.net
Tue, 04 Feb 2003 11:22:01 +0000
holger krekel <pyth@devel.trillke.net> writes:
> Hello,
>
> I'll try to take the discussion about a "unified approach"
> towards 'code block' or thunk handling into a fresh thread
> and present what Michael Hudson truthfully calls
> "a friendly competing approach".
I should point out that I stole that phrase from Guido (in PEP 283).
> I think we can may get away with only a "weak" keyword
> and allow the aforementioned encapsulation of execution
> events into an object like this:
>
> exec expr [with params]: suite
Gut reaction: ugh!
> where the expression is evaluated to return a
> "thunk" handler with these optional "execution" hooks:
>
> def __enter__(self):
> "before suite start"
>
> def __except__(self, type, value, tb):
> "swallow given exception, reraise if neccessary"
>
> def __leave__(self):
> """upon suite finish (not called if __except__
> exists and an exception happened)
> """
>
> The above "with" parameters (of the form name=expr, comma-separated)
> are bound in local (or global/nested) *and* handler instance
> namespace. The 'suite' is what we call "thunk".
>
> The above logic allows clean timely finalization for
> *multiple* ressources:
>
> exec autoclose() with f1=open(name1), f2=open(name2, 'w'):
> for line in f1:
> ...
> f2.write(...)
That looks messy.
> which would execute as follows
>
> a) autoclose() instance is created and stored as the
> "thunk"-handler
We need a name for these. I've been using "monitor" for a while, but
I'm not sure it's that apposite.
> b) f1/f2 are stored as attributes on the autoclose instance
>
> c) f1/f2 are put into the local/global namespace (and nested ones
> if rebinding is allowed)
>
> d) thunk executes (for line ...)
>
> e) autoclose 'leave' hook is called (with or without exception)
> and is implemented like this:
>
> def __leave__(self):
> for obj in self.__dict__.values():
> obj.close()
>
> f) thunk handler is removed
"Too much magic!"
> Because computing 'f1' may succeed but 'f2' can subsequently
> fail the assignments *have to* execute within "autoclose"
> control.
>
> Now on to the usage of the except hook. Nice use cases might be
>
> exec retry(maxretry=3, on=IOError):
> # do network io-stuff
> or
> exec skip_on(AttributeError, TypeError):
> some_object.notify_hook()
>
> but i am sure there are more. Exception handling is often
> ugly when inlined with the code. I think that stating
> 'exception behaviour' up-front allows to write nice
> readable constructs.
I am *still* not convinced that an __except__ hook is worth the pain.
Can you implement those for me?
> __exit__ versus __leave__
> ---------------------------
>
> One remark (mainly to Michael as he does that other
> patch) about the hook-name __leave__ versus __exit__.
> we may want to eventually allow 'yield' within the
> thunk and then '__exit__' would be misleading.
I guess. But enter/exit is just such a canonical pairing. To me,
leave is paired with arrive and arrive/leave doesn't make much sense.
> Here is the use case:
>
> exec self.mylock: # would lock/unlock on entering/leaving
> # the generator
> ...
> for whatever in something:
> yield whatever
> ...
yields already can't go in blocks with finally statements, right?
Would you propose calling the __enter__ method each time the generator
resumed?
> Or do you think that this (future) use case warrants
> yet another hook?
Guess :)
> If there is interest i can probably modify my patch
> to allow all of the proposed syntax so that you could
> play around with it.
>
> the next additional idea is not essential for my so-far
> proposal (but hopefully interesting, nonetheless).
I think all these proposals are in danger of bending the language into
a place it should not go. Still, we should write some PEPs, even if
they wind up rejected.
Cheers,
M.
--
Those who have deviant punctuation desires should take care of their
own perverted needs. -- Erik Naggum, comp.lang.lisp