[wxPython-users] Latest DelayedResult implementation
Josiah Carlson
jcarlson at uci.edu
Fri Sep 1 09:02:10 PDT 2006
"Oliver Schoenborn" <oliver.schoenborn at greenley.ca> wrote:
>
> 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:
My main reservations are that DelayedResult has a bunch of functionality
that most users wouldn't use, and/or wouldn't understand how to use
without reading a bunch of documentation. The three simplest cases I
provided in the 10-minutes-to-write AltDelayedResult.py would likely be
sufficient for the vast majority of users, and are also *very* simple to
understand.
For those people who want more sophisticated behavior, neither module
would likely be sufficient, so attempting to include additional
functionality isn't likely to be fruitful. The trick is providing the
right amount of functionality without confusing users.
As an example of a simple module that does its job well, look at your
own wx.lib.pubsub . What's the API?
pubsub.Publisher.subscribe(callable[, topic])
pubsub.Publisher.sendMessage([topic[, data[, notopic]]])
There are other bits and pieces, but that's the vast majority of what
people are going to use. It works, and it doesn't get in anyone's way.
> - the chaining doesn't need to be done by DelayedResult, I could just do
Chaining is more than what most users will likely want or need.
> - the exception forwarding is trivial to implement: true, but the
What I'm saying is that there is potential for a *very* simple API,
perhaps similar to the one I have provided, perhaps different. In my
'exception forwarding is trivial' statement, I was showing that any
module can provide exception forwarding without difficulty, so offering
it over the module I provided (in 10 minutes) is not on-topic.
> - it's not clear what I mean by channel: as in "communication channel",
> e.g. http://en.wikipedia.org/wiki/Channel_%28communications%29.
/I/ understand what it means in general, but in this context it is not
clear whether it means 1 listener, many listeners, 1 sender, many
senders, layered channels (think OSI 4/7 layer TCP/IP), etc.
I also don't believe that having variables that define channels is
generally useful. Pubsub did it right, and now DelayedResult is doing
it wrong.
> - 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
People learn by example. If in your examples and implementation you
have module X, people will tend to use module X unless they are
familliar with module Y and/or know that they are compatible.
Unfortunately, threading and thread are not really compatible. Threads
created by thread.start_new_thread() will not appear in threading's
activeCount(), enumerate(), etc. On the upside, at least threads
created by thread.start_new_thread() are daemonic (won't stop the
program from exiting), so at least a program can quit, but accounting
for those threads is difficult.
> - 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.
Generators are in use:
http://www.koders.com/?s=yield&_%3Abtn=Search&_%3Ala=Python&_%3Ali=*
And though we can't search for @ in the koders.com database:
http://www.koders.com/?s=decorate&_%3Abtn=Search&_%3Ala=Python&_%3Ali=*
...provides a handful, and Philip J Eby uses decorators quite a bit in
his PyObjC stuff (one of the original proponents, and who originally
convinced me of their use).
Never mind that decorators can make our lives in this case easier...
def CA(fcn):
def f1(fcn2):
def f2(*a, *k):
ReturnWithCallAfter(fcn, fcn2, *a, *k)
return f2
return f1
@CA(frame.method)
def LongRunningFunction(...):
...
Now any calls to LongRunningFunction will be automatically dispatched
with the ReturnWithCallAfter() mechanism, calling frame.method when done.
> > 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,
>
> 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()))
I claim that the 3 base mechanisms I provided earlier are sufficient for
the majority of uses. If your module requires that much code to get
what I consider to be the base mechanisms, then your module lacks the
easiest to understand functionality, while including functionality that
needs to be heavily documented and exemplified in order to be understood.
Remember: some people have difficulty getting the value of a text
control. You think they are going to get channels? Thread creation?
channel.getSender() (which is actually closer in functionality to
channel.getReciever(), as they will be recieving the output of the call...)
You've built a complex and complicated module and API. wxPython doesn't
need a module that provides *more* complication, it needs a module that
provides *less*.
> The same effect can be achieved with straitforward branching in the
> functions themselves:
That is what I'm saying. The chaining rules you provide are neither
necessary, nor sufficient, to handle chaining the way (I would argue)
most users would expect and/or want to do. So including it is more code
to maintain with little benefit.
- Josiah
More information about the wxpython-users
mailing list