PythonWin, python thread and PostQuitMessage?

Gabriel Genellina gagsl-py2 at yahoo.com.ar
Fri Mar 13 23:30:00 CET 2009


En Fri, 13 Mar 2009 17:59:34 -0200, <aloonstra at gmail.com> escribió:
> On 12 mrt, 18:43, "Gabriel Genellina" <gagsl-... at yahoo.com.ar> wrote:
>> En Thu, 12 Mar 2009 07:21:35 -0200, <arn... at sphaero.org> escribió:
>>
>> > I'm not so much involved in any Windows programming however I needed
>> > to write a client for the Windows platform. I have this very simple
>> > question which I've been unable to answer. I'm listening for keyboard
>> > strokes using the pyhook library. I'm doing this in a dedicated
>> > thread. The gui just controls the thread. When I want to pause
>> > listening for keyboard strokes I wanted to do a PostQuitMessage() to
>> > the thread. However this does not work since it either kills the whole
>> > app or just does not happen in the thread it's supposed to. I've now
>> > made an ugly workaround using PumpWaitingMessages and a delay.
>>
>> If you have a GUI, then very likely it has its own message loop, so you  
>> should not create another.
>>
>>
>>
>> > def run(self):
>> >    print "Wkeylog run called"
>> >    # Hook Keyboard
>> >    self.hm.HookKeyboard()
>> >    while self.log:
>> >            win32gui.PumpWaitingMessages()
>> >            time.sleep(0.02)
>>
>> > i can now just cancel the process by setting self.log to False. I
>> > wanted to do just:
>>
>> > def run(self):
>> >    print "Wkeylog run called"
>> >    # Hook Keyboard
>> >    self.hm.HookKeyboard()
>> >    win32gui.PumpMessages()
>>
>> Then, if you remove PumpMesages and PumpWaitingMessages, there is  
>> nothing  
>> left... so this thread is useless.
>> Perhaps you want to *process* keyboard events in another thread - in  
>> this  
>> case, use a Queue object to send events to the worker thread, from the  
>> main thread where the message loop resides.
>
> You are right however this case is a bit different. The application is
> a keylogger which listens for keyboard events. The GUI is done using
> Wx. They are different message loops. Under Linux I have no problem
> however in the case of Windows I don't know how to stop the keylogger.
>
> The Keylogger for Windows is very simple, see:
> http://retypingdante.svn.sourceforge.net/viewvc/retypingdante/trunk/inferno/src/rtd_Wkeylog.py?view=markup

This code uses PumpMessages just because it's a console application, and  
those do not have a message loop by default. A windowed application  
written in wx *already* has a message loop, so you don't have to provide  
your own.

Stopping the keylogger, in that code, means calling the cancel() method,  
by any means you want. It has nothing to do with a message loop, AFAICT.

> As you can see in the cancel function I cannot use
> win32gui.PostQuitMessage(1) since it kills the whole app, including
> Wx, and not just the thread. I cannot mix the eventloops of Windows
> and Wx AFAIK so I put it in its own thread. I'm already using Queue
> objects to pass the data between threads.

I still don't understand why you use a separate message loop. wx provides  
its own, and it should be enough - worse, a second message loop may  
adversely affect the application. And without a separate message loop, the  
separate thread has no sense either.

Anyway, if you insist, it's more efficient to wait using an Event object:

def __init__(...):
   ...
   self.finished = threading.Event()

def run(self):
   self.hm.HookKeyboard()
   self.finished.wait()

def cancel(self):
   self.hm.UnhookKeyboard()
   self.finished.set()

-- 
Gabriel Genellina




More information about the Python-list mailing list