Methods not returning when called from wxPython

Class library usage, coding and language questions.
domperez
Posts: 6
Joined: Tue Oct 30, 2007 4:23 pm

Methods not returning when called from wxPython

Post by domperez » Tue Dec 04, 2007 11:45 pm

I've run into a problem. When I call some Ranorex methods, FormFindTitle for example, from a thread in a wxPython app it never returns. If I make the same call from the wx main thread or from a thread in a non-gui script it works fine.

I've attached some sample code so you can hopefully reproduce what I'm seeing. If you run the attached script with no args it will run the non-gui thread, if you run it with "gui" as the arg you will see a simple dialog with 2 buttons. The Test WX button calls FormFindTitle from the main thread and the Test Thread button spawns a thread and make the same call.

I need to do this because I have a test run and report tool written with wxPython.

Am I missing something obvious?

Thanks

Code: Select all

#!/usr/bin/python
import sys
import threading
import os            
import wx
import imp

RANOREX_BINPATH = "C:\\Program Files\\Ranorex 1.3\\Bin\\Python2.5\\"
Ranorex = imp.load_dynamic('RanorexPython', RANOREX_BINPATH + 'RanorexPython.dll')


#Define Main Window
class MyFrame(wx.Frame):
    
    frameStyle = wx.MINIMIZE_BOX | wx.CLOSE_BOX | wx.SYSTEM_MENU | wx.CAPTION | wx.RESIZE_BORDER
    def __init__(self):
        #init fram and panel
        wx.Frame.__init__(self, None, -1, title="Test Utility",
                          pos=(200,200), size=(200, 200), style = MyFrame.frameStyle)
        self.panel = wx.Panel(self, -1, (-1,-1), (200, 200))
        
        #init buttons
        self.TestButton = wx.Button(self.panel, -1, "Test WX", (30, 20))
        self.TestThreadButton = wx.Button(self.panel, -1, "Test Thread", (30, 60))
        
        #init bindings
        self.Bind(wx.EVT_BUTTON, self.OnTestThreadButton, self.TestThreadButton)
        self.Bind(wx.EVT_BUTTON, self.OnTestButton, self.TestButton)
        self.Bind(wx.EVT_IDLE, self.OnIdle)

    def OnIdle(self, event):
        pass

    def OnTestButton(self, event=None):
        print "WX Test should work!"
        ret = Ranorex.FormFindTitle("Audia", Ranorex.MATCH_FROM_START , True, 500)
        print "Return is: ", ret

    def OnTestThreadButton(self, event=None):
        print "Thread Test from WX will hang!"
        t = testthread()
        t.start()
                        
#Define main app and NIC selection dialog
class MyApp(wx.App):
    def __init__(self, redirect=False, filename=None):
        wx.App.__init__(self, redirect, filename) 
        
        #init and show the main gui    
        self.MainFrame = MyFrame()
        self.MainFrame.Show(1)
        self.SetTopWindow(self.MainFrame)


class testthread(threading.Thread):
    def __init__(self):
        print "Initializing thread"
        threading.Thread.__init__(self)
        
    def run(self):
        print "Starting Thread if called from WX this next call will not return"
        ret = Ranorex.FormFindTitle("Audia", Ranorex.MATCH_FROM_START , True, 500)
        print "Return is: ", ret


if __name__=="__main__":
    
    if len(sys.argv) > 1 and sys.argv[1].upper() == "GUI":
        app = MyApp()#redirect, file)
        app.MainLoop()
    else:
        t = testthread()
        t.start()
    

User avatar
Support Team
Site Admin
Site Admin
Posts: 11709
Joined: Fri Jul 07, 2006 4:30 pm
Location: Graz, Austria

Post by Support Team » Thu Dec 06, 2007 6:24 pm

Well, that took me some time :?

It seems to be a problem with Python's global interpreter lock. The FindFormTitle method causes a message to be send to the WX Frame's message loop to get the name of the WX window. I assume that this in turn tries to access some Python object which is blocked by the global interpreter lock.

We're currently working on the problem and hope to announce a solution soon.

Regards,
Alex
Ranorex Support Team

User avatar
Support Team
Site Admin
Site Admin
Posts: 11709
Joined: Fri Jul 07, 2006 4:30 pm
Location: Graz, Austria

Post by Support Team » Sun Dec 09, 2007 1:54 pm

It was indeed a problem with Python's global interpreter lock. A deadlock may occur if a Python GUI process calls Ranorex methods from a thread other than the GUI thread.

This problem will be fixed in the upcoming Ranorex 1.3.1 release. :)

Alex
Ranorex Support Team