+1  A: 

You could wrap the two functions into another function and call idle_add on this function:

def update_and_print(self):
        self.updateText()
        print self.textEntry.get_text()

def startThread(self):
        gobject.idle_add(self.update_and_print)
balpha
The problem is that in my actual code, I'm not always running the same line after calling the function. Depending on the context, I may call something else after the function call.
Can't you check for this particular condition inside the update_and_print callback?
balpha
Well, also the work after the GUI update is CPU intensive, which would block the main GUI loop, and I'm not going to spawn a new thread to do the work that the initial thread was created for.
+2  A: 

Don't try to update or access your GUI from a thread. You're just asking for trouble. For example, the fact that "get_text" works at all in a thread is almost an accident. You might be able to rely on it in GTK - although I'm not even sure about that - but you won't be able to do so in other GUI toolkits.

If you have things that really need doing in threads, you should get the data you need from the GUI before launching the thread, and then update the GUI from the thread by using idle_add, like this:

import time
import gtk
import gobject
from threading import Thread

w = gtk.Window()
h = gtk.HBox()
v = gtk.VBox()
addend1 = gtk.Entry()
h.add(addend1)
h.add(gtk.Label(" + "))
addend2 = gtk.Entry()
h.add(addend2)
h.add(gtk.Label(" = "))
summation = gtk.Entry()
summation.set_text("?")
summation.set_editable(False)
h.add(summation)
v.add(h)
progress = gtk.ProgressBar()
v.add(progress)
b = gtk.Button("Do It")
v.add(b)
w.add(v)
status = gtk.Statusbar()
v.add(status)
w.show_all()

def hardWork(a1, a2):
    messages = ["Doing the hard work to add %s to %s..." % (a1, a2),
                "Oof, I'm working so hard...",
                "Almost done..."]
    for index, message in enumerate(messages):
        fraction = index / float(len(messages))
        gobject.idle_add(progress.set_fraction, fraction)
        gobject.idle_add(status.push, 4321, message)
        time.sleep(1)
    result = a1 + a2
    gobject.idle_add(summation.set_text, str(result))
    gobject.idle_add(status.push, 4321, "Done!")
    gobject.idle_add(progress.set_fraction, 1.0)


def addthem(*ignored):
    a1 = int(addend1.get_text())
    a2 = int(addend2.get_text())
    Thread(target=lambda : hardWork(a1, a2)).start()

b.connect("clicked", addthem)
gtk.gdk.threads_init()
gtk.main()

If you really, absolutely need to read data from the GUI in the middle of a thread (this is a really bad idea, don't do it - you can get into really surprising deadlocks, especially when the program is shutting down) there is a utility in Twisted, blockingCallFromThread, which will do the hard work for you. You can use it like this:

from twisted.internet.gtk2reactor import install
install()
from twisted.internet import reactor

from twisted.internet.threads import blockingCallFromThread
from threading import Thread

import gtk

w = gtk.Window()
v = gtk.VBox()
e = gtk.Entry()
b = gtk.Button("Get Text")

v.add(e)
v.add(b)
w.add(v)

def inThread():
    print 'Getting value'
    textValue = blockingCallFromThread(reactor, e.get_text)
    print 'Got it!', repr(textValue)

def kickOffThread(*ignored):
    Thread(target=inThread).start()

b.connect("clicked", kickOffThread)
w.show_all()

reactor.run()

If you want to see how the magic works, you can always read the source.

Glyph