views:

69

answers:

2

My intention was to use pyGTK's main loop to create a function that blocks while it waits for the user's input. The problem I've encountered is best explained in code:

#! /usr/bin/python

import gtk

def test():
    retval = True
    def cb(widget):
        retval = False
        gtk.main_quit()

    window = gtk.Window(gtk.WINDOW_TOPLEVEL)
    button = gtk.Button("Test")
    button.connect("clicked", cb)
    button.show()
    window.add(button)
    window.show()

    gtk.main()
    return retval

if __name__ == "__main__":
    print test() # prints True when the button is clicked

It seems that the exact order of instructions (change value of retval, then exit main loop) isn't being followed here.

Is there any way around this, or is this just bad design on my part?

+2  A: 

What is happening is that when python sees foo = bar as the first reference to foo in a function it assumes that it is a local variable. In python3k you can get around this by using the nonlocal keyword. For 2.x you can wrap your retval in a list so that you aren't directly assigning to it.

retval = [True]
def cb(widget):
    retval[0] = False
    gtk.main_quit()
...
return retval[0]

not really an elegant solution, hence the addition of nonlocal in 3.x (PEP)

cobbal
hmm.. What if I'm using 2.6?
int3
Indeed that fixed it, thanks! The PEP you linked to also provides another solution (using a 'Namespace' class). I'll have to decide which is less ugly :P
int3
+1  A: 

This is the dialog pattern. Use a gtk.Dialog. Dialog.run() blocks exactly how you need it to, and returns the dialog's return code.

Ali A