> From: Josiah Carlson [mailto:jcarlson@uci.edu]
> Also, I don't particularly understand how one uses your
> module, maybe I'm just an idiot. Presumably one can use it to
> handle function calling, result posting, etc., for the
> results of worker threads, but it's just not fitting in my head.If you only have a worker thread that returns a result and that's it,
then there is not much point in using DelayedResult, except that it
aggregates the two main inter-thread comms mechanisms available in wx
(so for a novice it might be a good place to start). Even the ability to
open/close a channel is mostly sugar, since you can always create a flag
to keep track of this, but it provides the synchronization of the flag
state so it's a little easier there.
So here's the deal; I have no idea what you mean by "channel". In the 5
years I've been using threads with Python, I've used queues, locked
structures, and more recently with wxPython, event posting. Maybe
"channels" fit a particular mind-set that I don't have, or maybe they
are just different terminology for what I've been using and teaching.
At this point, I don't know.
The real benefit is if you have a call chain on the return value: it
allows you to preserve almost entirely the single-threaded call
structure.
Um...that's *exactly* what the mechanism I provide offers. You write a
function that offers the single-threaded call structure you want, and
you call it. There, you are done.
Exceptions can also be transmitted, which is not the case
with plain thread/wxCallAfter etc. I wish I could express this more
clearly, sorry, my failure.
This is trivially implemented via...
try:
r = dict(result=fcn(*args, **kwargs))
except:
r = dict(error=sys.exc_info())
#use whatever return mechanism you have specified
> There are 6 usable functions in the attached module, which
> offer returns via wx.PostEvent, wx.CallAfter, and direct
> calling. I'm not providing documentation because they are
> fairly straightforward. I'm curious as to what advantages
> your module offers over the attached AltDelayedResult.py .The chaining, the choice of threading mechanism, the channel open/close,
the exception propagation from the worker thread, binding of call
arguments.
1. I don't think your chaining mechanism is generally useful.
2. There are exactly two threading mechanisms currently in the Python
standard library, choosing threading over thread isn't a difficult
choice to make. Also, both your test cases and your documentation use
thread.
3. I don't understand what you mean by channels, so I don't know if they
are a useful abstraction.
4. Exception propagation is trivial to implement, as I've shown above.
5. See my later comments on currying.
> Note that generally speaking, call chaining is difficult to
> accomplish unless you specifically design your
> functions/methods for call chaining.
> For the user, it is much better if they instead write their
> own chaining mechanism...Multi-threading always forces some redesign. But DelayedResult I think
helps limit this: you can just split your functions into "before
thread"/"after thread" parts.
The threads that I've been using are generally one of two different
kinds:
1. daemon worker threads (gets jobs from a queue)
2. non-daemon worker threads (call a function that returns a result)
Generally people who have designed without threads in mind have a set of
functions pieces of their computation. The only thing that is required
of such functions is that they take arguments, can call each other, and
return their result in some fashion. And you know what? People who have
written their functions with threads in mind have the exact same thing,
except that sometimes they use different mechanisms to get arguments
and/or return results.
In that sense, any API that makes it more difficult for a user to say
'call function X with arguments A, B, C and give me the results like Y'
is too big and/or too complicated. The API I provided is self
documenting, simple to use, and will do exactly what the user expects of
it. I don't know what to expect from your library, maybe you can help
me.
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)
What would it take to do the same thing with the version of the library
you most recently posted?
> def chain(arg1, arg2, ...):
> r = fcn1(arg1, ...)
> r = fcn2(arg3, r, ...)
> r = fcn3(r)
> ...
> return r
>
> Then they can use any delayed result implementation, and
> don't need to rely on a particular API for their chaining.This has several disadvantages:
1) Chaining of transformation on the return value is often an
implementation detail, which is not compatible with the technique you
suggest.
This entire discussion is about implementation details, and the 'send me
a callable and I'll call it' API that I'm providing *is* compatible with
chaining based on return value (it is actually compatible with *any*
chaining rule): you write the chaining rules yourself!
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(...)
...
2) All the args appear in one function call, not good
That's a subjective statement. It has precisely the number of arguments
necessary to get the job done. It may get long, but that isn't stopping
anyone from separating out functional blocks and having the GUI do
further dispatch if it bothers them. One convenient thing about such a
mechanism is that you can offer GUI updates as the various bits of the
job get done.
3) No currying available (or user has to implement it... then why not
use DelayedResult)
Um, currying will be shipped in the Python 2.5 standard library, and
various base implementations have been offered in PEP 309 since last
year: PEP 309 – Partial Function Application | peps.python.org
I will also mention that even though it has been available via various
methods since at the latest 2003, I've never actually seen it used "in
the wild".
- Josiah
···
"Oliver Schoenborn" <oliver.schoenborn@greenley.ca> wrote: