On Mar 28, 2007, at 6:03 PM, Antonino Ingargiola wrote:
> On 3/28/07, Ken McIvor <[EMAIL PROTECTED]> wrote:
>> You should probably do the acquisition asynchronously by running it
>> in a separate thread.
<snip>
>
> That's exactly what I'd like to do. The problem is that if I run
> gtk.main() (the gtk main  GUI loop) in a separate thread the program
> stops until I do something on the GUI (for example passing the mouse
> on it).

Does it do this if you run gtk.main() in the main thread (e.g. the  
interpreter prompt) while doing something else in a background thread?

> My understanding so far is the following.  When the function
> that execute gtk.main() is executed, python doesn't switch thread
> until either 100 bytecode instructions are executed or since an I/O
> (potentially) blocking operation in executed.

I think you're more or less correct but are unaware of one important  
factor.  Here's my understanding of how multithreading works in  
Python...

Thread switching is controlled by something called the Global  
Interpreter Lock, which is implemented in an abstract way on top of  
an OS lock/mutex object.  Only one Python thread runs at a time  
because the Python interpreter requires a thread to hold the GIL  
before it can execute bytecode instructions.  The running thread  
holds the GIL while is executes 100 instructions.  During this time  
other Python threads block waiting to acquire the GIL.  After it has  
executed its 100 instructions, the running thread releases the GIL  
and then attempts to reacquire it.  The OS ensures that things are  
fair by preventing one thread from reacquiring the GIL over and over  
again when other threads are also waiting for it.

Python doesn't actually detect you do something that will block the  
thread, like an I/O operation.  Instead, the C code implementing an I/ 
O operation like file.write() releases the GIL before performing the  
operation.  This allows a different thread to acquire it and run some  
more bytecode instructions while the first thread performs its I/O  
operation.

> When I'm doing nothing on the  GUI application, neither 100 byte  
> code instructions are executed in the thread neither an I/O call is  
> performed, so the whole program (including the *other* threads)  
> stalls.

I'm not sure on the details, but the C code that implements gtk.main 
() almost certainly releases the GIL before running the GUI event  
loop.  Otherwise things like iPython wouldn't be able to run the GUI  
in a separate thread.  So, that's probably not the problem.

It's possible that there's another lock that's used to protect access  
to the gtk module.  If that's the case you could be causing deadlock  
by calling making gtk calls from multiple threads.  In my experience  
it's best to stick to the one-thread rule: the thread that runs the  
GUI's event loop is the only thread that's allowed to do anything  
related to the GUI.

> Basically, I don't know which is the right way to put a Gtk GUI in
> background, while another thread get the data asynchronously.

You probably want to put the GUI in the main thread.  The main thread  
is the only thread in a Python program that receives the  
KeyboardInterrupt exception when the process receives a SIGINT (i.e.  
when the user hits ^C in the shell).  Also, most Python GUI toolkits  
require their event loops run from the thread that originally  
imported the module.

> BTW, the timer idea is good and eliminates the need to call
> asynchronously the GUI thread to update the plot, which seems (the
> latter case) not very simple to do.

Yep.  It's impossible to inject arbitrary code into a Python thread;  
the thread has to figure out what it's supposed to do by periodically  
polling something or retrieving some kind of message by blocking on a  
queue.  Blocking on a queue isn't an option for the GUI thread.

You might be able to trigger Gtk signals from a separate thread but  
in my experience tricks like that can be, well, tricky.

> Thanks to your suggestion to use the image.set_data method I've
> created a simplified script (pasted at the end) that demonstrate how
> to do live-update while acquiring (jep!).

Glad I could help!  :-)

> The last think I'm not yet able to do is to update the colorbar to
> autoscale with the new incoming data. The the script that follows
> tries to update the colorbar too but it does not work (on matplotlib
> 0.87 at least).

I have no idea if this will help, but you might need to call  
AxesImage.changed() after calling AxesImage.set_data().

Ken



-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Reply via email to