PythonWin, python thread and PostQuitMessage?

Discussion in 'Python' started by arnaud@sphaero.org, Mar 12, 2009.

  1. Guest

    Hi All,

    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.

    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()

    However I'm unable to stop this process. Can anyone shred al light
    here?

    Rg,

    Arnaud
     
    , Mar 12, 2009
    #1
    1. Advertising

  2. En Thu, 12 Mar 2009 07:21:35 -0200, <> 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.

    --
    Gabriel Genellina
     
    Gabriel Genellina, Mar 12, 2009
    #2
    1. Advertising

  3. Guest

    On 12 mrt, 18:43, "Gabriel Genellina" <> wrote:
    > En Thu, 12 Mar 2009 07:21:35 -0200, <> 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.
    >
    > --
    > Gabriel Genellina


    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.sourceforg.../trunk/inferno/src/rtd_Wkeylog.py?view=markup

    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.

    Arnaud
     
    , Mar 13, 2009
    #3
  4. En Fri, 13 Mar 2009 17:59:34 -0200, <> escribió:
    > On 12 mrt, 18:43, "Gabriel Genellina" <> wrote:
    >> En Thu, 12 Mar 2009 07:21:35 -0200, <> 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.sourceforg.../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
     
    Gabriel Genellina, Mar 13, 2009
    #4
  5. Guest

    On 13 mrt, 23:30, "Gabriel Genellina" <> wrote:
    > En Fri, 13 Mar 2009 17:59:34 -0200, <> escribió:
    >
    >
    >
    > > On 12 mrt, 18:43, "Gabriel Genellina" <> wrote:
    > >> En Thu, 12 Mar 2009 07:21:35 -0200, <> 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
     
    , Mar 14, 2009
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Richard Lee
    Replies:
    2
    Views:
    439
    Daniel Dittmar
    Jul 22, 2003
  2. stephan
    Replies:
    0
    Views:
    440
    stephan
    Jul 30, 2003
  3. ¹âÒõµÄ¹ÊÊÂ

    Where to find the Pythonwin for Python 2.3?

    ¹âÒõµÄ¹ÊÊÂ, Feb 17, 2004, in forum: Python
    Replies:
    2
    Views:
    641
    Mark Hammond
    Feb 17, 2004
  4. gaoshan
    Replies:
    0
    Views:
    310
    gaoshan
    Jun 8, 2004
  5. escalation746
    Replies:
    3
    Views:
    1,431
    Sridhar Ratnakumar
    Feb 9, 2010
Loading...

Share This Page