I'm trying to use threads and I'm having problems with wxWindows.
What I'm looking for help on is what can be done with wxWindows in a
I have a thread-safe Python method that reads data and places the data
into a wxGrid whose parent is a wxNotebook. The code basically is:
create a grid of correct size
insert column labels
add grid as a page in the notebook
update the grid
This code doesn't work (grid doesn't display data) even though I can
verify that the data is being inserted into the grid. Some times the
entire Python process hangs. When I comment out all of the wxWindows
calls the thread so far hasn't failed (Yes I know that this changes
the timing, but I don't think that this is the problem).
> I'm trying to use threads and I'm having problems with wxWindows.
> What I'm looking for help on is what can be done with wxWindows in a
> I have a thread-safe Python method that reads data and places the data
> into a wxGrid whose parent is a wxNotebook. The code basically is:
> create a grid of correct size
> begin batch
> insert column labels
> insert values
> end batch
> add grid as a page in the notebook
> update the grid
> This code doesn't work (grid doesn't display data) even though I can
> verify that the data is being inserted into the grid. Some times the
> entire Python process hangs. When I comment out all of the wxWindows
> calls the thread so far hasn't failed (Yes I know that this changes
> the timing, but I don't think that this is the problem).
> Any ideas?
First a little background:
Python only allows one thread at a time to actually be executing Python code,
so there is a global intermpreter lock that must be aquired and released at
the appropriate times. wxPython code releases the lock before calling any
C++ method and then aquires it again before returning to Python. For
callbacks from wxWindows to Python code (event handlers, etc.) then wxPython
not only aquires the lock but also restores the thread state of the
GUI-thread*, IOW, makes it the active thread.
* What I call the GUI-thread is whichever thread was active when the wxApp
object was created and its OnInit was called.
Since on most platforms the X libraries are not thread safe, the general rule
is to only interact directly with the GUI from a single thread, and to use
some indirect method from other threads. wxWindows generally follows this
model and it fits nicly with how wxPython handles the global interpreter lock
as well. wxPython knows about just one thread and restores it when
Now to your problem:
It sounds like you are calling methods of the grid from an alternate thread,
(a non GUI-thread.) While in some cases this may be okay, if an event is
generated then there is definitly the potential of a deadlock situation when
wxPython tries to aquire the interpreter lock with a different thread than
the active one. This sounds like what is happening when the whole process
If you can find a way to not do the grid method calls directly from your
alternate thread then things will run better. Probably the easiest way to do
this is with Events. You can send an event to a window from an alternate
thread using wxPostEvent(window, event) using either an event class you
create yourself or one of the stock event classes. See
wxPython/demo/Thread.py for an example. wxPostEvent makes a copy of the
event and places it in an internal queue and then does some platform specific
thing (sends a dummy message on MSW) to wake up the main Idle handler in the
GUI-thread where the events are actually sent to the window.
Another spin on this approach is to create a queue of "command" objects using
the thread-safe Queue.py from the standard python library. The alternate
thread can add items to the queue and then send a wxEvent to the window. The
window's event handler can then read items from the queue and do what they
instruct, (set column labels, insert cell values, etc.) This might be a bit
more efficient than sending an event containing each "command."