wxpythondeadlockpyhooklockup

pyHook and wxPython - App Freezes when typing in itself


I have a small python application that creates a wxPython Frame and then uses pyHook to hook the keyboard. The Frame contains a TextCtrl. When the text in the control is changed, a thread is created to do some process (in this case, just a large loop to simulate a long process).

If I focus on the TextCtrl and mash the keyboard, the app completely locks up. If I remove the pyHook code the app does not lock up. If I make the long process shorter (only loop 10 iterations for example), the app does not lock up.

There seems to be something about using pyHook when typing in the same application that created it.

Note that if I create the keyboard hook and call PumpMessages from the main thread, the app does not lock up, but I ideally want to create the hook on a separate thread.

Any ideas?

Thanks Mike

import threading
import pyHook
import pythoncom
import wx

class LargeTaskProcessor(object):

    def do_task(self):
        iterations = 1000000
        # Simulate some large process
        for i in range(iterations):
            pass

class TestFrame(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, 1, 'Title', size=(400, 400))

        global_sizer = wx.BoxSizer(wx.VERTICAL)

        self.test_textbox = wx.TextCtrl(self, style=wx.TE_PROCESS_ENTER)
        self.Bind(wx.EVT_TEXT, self._event_happened, self.test_textbox)
        global_sizer.Add(self.test_textbox)

        self.SetAutoLayout(True)
        self.SetSizer(global_sizer)
        global_sizer.Fit(self)
        global_sizer.SetSizeHints(self)
        self.Layout()

    def _event_happened(self, event=None):
        action_thread = threading.Thread(target=obj.do_task)
        action_thread.start()

def hook_the_keyboard():
    hookManager = pyHook.HookManager()
    hookManager.HookKeyboard()
    pythoncom.PumpMessages()

if __name__ == '__main__':
    app = wx.App()

    obj = LargeTaskProcessor()

    dialog_instance = TestFrame()
    dialog_instance.Show()
    dialog_instance.Raise()

    # Create the hook manager and call PumpMessages on a separate thread
    theThread = threading.Thread(target=hook_the_keyboard)
    theThread.start()
    app.MainLoop()

Solution

  • Try remove pythoncom.PumpMessages()

    From pyHook turorial said:

    When run, this program just sits idle and waits for Windows events. If you are using a GUI toolkit (e.g. wxPython), this loop is unnecessary since the toolkit provides its own.