how to start a new thread from a GUI

Brian Kelley bkelley at wi.mit.edu
Fri Aug 17 12:28:29 EDT 2001


Graham Ashton wrote:

>If you made the client and server talk to each other via something like
>XML-RPC then you could even put your daemon on a different machine if you
>wanted, allowing clients to connect over the network and farm jobs out to
>a server.
>
>  http://www.onlamp.com/pub/a/python/2000/11/22/xmlrpcclient.html
>
>With RPC you can execute procedures, or methods, on remote systems. So
>you'd have one RPC method to start the processing job, and one to
>retrieve the status of the job or the final answer.
>

Right, this is just a wire protocol albeit with a simpler interface than 
Corba/COM etc.  But you still need to hook into the GUI's event loop to 
handle events.  You can't just block and wait for a response, the GUI 
still needs to respond to events.

This has been my experience with every GUI system I've looked at (except 
mozilla actually I think they run javascript functions in seperate 
threads of execution).  The issue is that you have to know how to hook 
into the event loop using the GUI toolkits version of signal or alarm or 
whatever.  Like I mentioned there are plenty of remote proxies out there 
to run processes on other machines, the trick is keeping the GUI 
responsive during long running processes.

What I would like to see is a lightweigh framework for handling any 
proxy that delegates to the toolkit, something like:
class LongRunningTask:

class TkinterTask(LongRunningTask)

class GtkTask(LongRunningTask)
class QTTask(LongRunningTask)
class XMLRPCTask(LongRunningTask)

Each task would preserve a model, controller interface where a model is 
a class (or interface, see below) and a controller is a class (or interface)

 self.task = GtkTask(controller=self, task=task)

GtkTask starts up task and delegates all calls to the task in it's new 
process.  All calls from the task to the controller are also delegated 
appropriately.  Now the task can be started out of process, in process, 
through a corba mechanism or what not.

I gave a talk at the O'Reilly Open Source conference about this type of 
thing.  The gist was to automagically start a task running out of 
process and hook up an event model that could send python messages back 
and forth to the children through any applicable wire protocol.  Mitch 
Chapman showed me the joys of actually hiding this from the developer 
back at Bioreason.  He made a GtkTask class that automagically ran 
relatively arbitrary python code in another process.  We made a mistake 
and explained the process to our developers but would have been much 
better off just saying "do this and don't worry about it"

For example the GtkTask starts up a piece of code in another process and 
uses pipes to send messages back and forth so when the user executes 
something like

                     wire protocol
Controller  <---------------->  Task
Event Loop                               Task event Loop

class Controller:
 result = self.task.doSomething()

this gets propgated across the wire protocol and gets executed in the 
task's namespace.  XMLRPC is a dandy wire protocol for doing this but it 
still needs to interact with the GUI's event loop, especially for events 
(i.e. when the task has to call a method on the Controller for instance)

The Task event loop is a bit simpler since we can use Python's built in 
select, signal or whatever to do the polling.

Obviously this would be limited in scope for simplicity.  The relevant 
points are
1) Uses a controller/model method (where the model is a task here)
2) Asynchronous I/O between controller and model
3) The class has do be it's own interface, that is no __getattr__ or 
__setattr__ tricks or similar.  This is for the automagic part.
4) Only marshallable/picklable data can be seent between the two and all 
data is immutable.  I.e. changing an object on one side doesn't change 
it on the other, it must be passed back.
5) Processes must be killable!  This is easier with pipes and pids and 
the like, it's harder with COM/Corba and threads.

This would handle 99% of the issues I have seen for GUIs diehards can 
work with COM/Corba (although they still have to hook into the event loop!)

===========
About interfaces:
I used to think that Python's classes were pretty good descriptions of 
interfaces.  I still think that they are (within reason).  The problem 
is that python is to dynamic.  For example I wrote a COM policy to wrap 
arbitrary python objects and query their interfaces so that any object 
could become a COM object.  There was one simple rule:

Any method/attribute that begins with "_" was considered private and not 
exposed.

It worked well but I had a major problem.  Cached or lazily evaluated 
attributes.  Oops, they can't be seen across the wire.

That said, it worked well enough to start me thinking about the task 
issue at hand.  I think this is a small price to pay in this 
circumstance and have had pretty good luck telling my developers about 
how to use the wrapped classes.  That being said I sat in on Jim 
Fulton's "Future of Zope" birds of a feather and quickly realized that 
the added complexity of interfaces reduces time and effort down stream. 
 I think this is possibly more true with novices ironically enough.

Hopefully I'm making sense.  I know Mitch will correct me on invalid 
points at least.

Cheers

Brian Kelley
Whitehead Institute for Biomedical Research





More information about the Python-list mailing list