PythonWin, python thread and PostQuitMessage?

aloonstra at gmail.com aloonstra at gmail.com
Sat Mar 14 07:09:20 EDT 2009


On 13 mrt, 23:30, "Gabriel Genellina" <gagsl-... at yahoo.com.ar> wrote:
> En Fri, 13 Mar 2009 17:59:34 -0200, <aloons... 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/i...
>
> 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

You're right. Last night I dived into all this message looping thing
and I don't even have to use PumpMessages(). I got it working from
within wx using its messageloop. So I don't need a seperate thread no
more.

Thanks for your suggestions.

Arnaud



More information about the Python-list mailing list