[wxPython-users] Latest DelayedResult implementation
Oliver Schoenborn
oliver.schoenborn at greenley.ca
Fri Sep 1 05:31:29 PDT 2006
Hi Josiah,
> -----Original Message-----
> From: Josiah Carlson [mailto:jcarlson at uci.edu]
> Sent: August 30, 2006 2:02 AM
>
> def chain(arg1, arg2, ...):
> r = fcn1(arg1, ...)
> r = fcn2(arg3, r, ...)
> r = fcn3(r)
> ...
> return r
IIUYC, your main reservations re DelayedResult are:
- the chaining doesn't need to be done by DelayedResult, I could just do
the above that you propose: actually, DelayedResult doesn't have to do
the chaining, you can do your own; OR you can use the one provided by
DelayedResult; choice is always good, and in all cases so far I have
been able to use the DelayedResult builtin and save myself myself tons
of time.
- the chaining method that you propose is better: I disagree on a couple
of fronts that I've already mentioned but I'll try differently:
- an exception thrown from fcn3 will not go through fcn2 so the
exception handling of the single-thread algorithm (don't forget
we're talking about worker threads so this is an important
point) is not preserved
- your method prevents encapsulation: during setup (ie the code
executed up to, but not includng, starting the thread), method
Foo.foo(channel) may call internally Bar.bar(channel) which
might internally call Baz.baz(channel) and the last one is
the one to create the thread; the return of result must do
a reverse set of calls from Baz up to Foo on result handlers;
I really do NOT want Foo.foo() to have to know about Baz.
- the exception forwarding is trivial to implement: true, but the
example you give still has more code than I want to bother with, and IMO
syntax is simpler with DelayedResult.Sender. Plus if you really want to,
DelayedResult allows you to do your own implentation for trickier
situations, or use boiler plate code for the majority of cases; choice
is always good.
- it's not clear what I mean by channel: as in "communication channel",
e.g. http://en.wikipedia.org/wiki/Channel_%28communications%29.
- DelayedResult forces user to use thread instead of threading: that's
simply not true; the fact that I use thread in test cases is completely
irrelevant to usage of module
- currying (which I used in the loose send, btw, of binding some
function arguments to values, leaving me with a function of fewer
arguments) is not used "in the main stream": neither are decorators or
generators, that depends on how one programs; I have used argument
binding quite a bit in the context of DelayedResult. Even if recipes
exist to provide it, it's nice to have it available in DelayedResult
without having to get yet another module, extra call to curry the
function, etc.
> With the API I provided, say I have a function foo that I
> want to call with arguments a,b,c and get results back via
> wx.CallAfter on goo, I would do:
> ReturnWithCallAfter(goo, foo, a, b, c)
DelayedResult leaves it up to you (intentionally) to create/manage your
thread function. So I end up with exactly the same call as you,
ReturnWithCallAfter(goo, foo, a,b,c)
with e.g. (not tested)
def ReturnWithCallAfter(listener, fn, *args):
def threadedFn(fn, sender, *args):
sender.sendThreadResult(fn(*args))
channel = byCall(listener, *args)
thread.start_new_thread(threadedFn, (fn, channel.getSender()))
Minor edits sufficient if you want to use 'threading' isntead of
'thread'.
> I will also mention that the chaining mechanism you offer has
> no way of performing alternate calls based on output and/or
> result (unless you directly return to the GUI), which is one
> of the reasons why I didn't think it was necessary to offer
> built-in chaining.
>
> def chain(a, b, c):
> d = fcn1(a)
> if condition(a, d, b):
> e = fcn2(...)
> else:
> e = fcn3(...)
> ...
The same effect can be achieved with straitforward branching in the
functions themselves:
def chain(a, b, c):
d = fcn1(a)
e = fcn23(a,d,b)
...
def fcn23(a,d,b):
if condition(a, d, b):
return 'hi'
else:
return 'lo'
There is only one path back to the listener from the thread. Any
conditions can be handled by a callable along the channel. In the event
that there is absolutely no other design possible (most likely due to
legacy constraints) and one really really needs a branch, one could
easily, as I said, bypass the DelayedResult chaining since it doesn't
force it on the user. Actually DelayedResult even allows user to
"partially" bypass the chaining.
Cheers,
Oliver
More information about the wxpython-users
mailing list