Is this hard?

I am introducing Python to my students and want to make a simple, interactive program that will, while it's running, 'listen' for any keyboard events. That is, I don't want to include an 'input' statement - that would pause execution till someone answered. I just want it to keep running, say, printing an 'a' on the screen every 10 seconds, until the user types a 'b'. Then printing a 'b' every 10 seconds till the user types in some other character...

It seems that this should not be hard; something with sys.stdin, perhaps. The hours I've spent on it are getting embarrassing.

I've fooled around with it and looked though books and the only solution I've come up with was to import pygame.py and use its event handling. This seems like massive overkill for what should be an easy matter.

I'm using IDLE with MacPython 2.5.1 on Mac OS 10.4.11

Thanks for any help on this problem.

Neal C.

import threading
import time

class getb(threading.Thread):
  def __init__ (self,printa):
    threading.Thread.__init__(self)
    self.printa=printa
  def run(self):
    while True:
      k=raw_input()
      if k=="b":
        self.printa.stop=True
        break

class printa(threading.Thread):
  def __init__ (self):
    threading.Thread.__init__(self)
    self.stop=False
  def run(self):
    while not self.stop:
      print "a"
      time.sleep(10)

t1=printa()
t2=getb(t1)
t1.start()
t2.start()

Thanks, slate, for considering this problem.

I brought up IDLE, copied & pasted your script into a new module, and ran it - not much happened: it typed an 'a' and then just sat there. The typing an 'a' every 10 seconds wasn't happening. Typing in a <CR> twice (with pauses) produced another 'a' and so on; typing in a «b<CR>» stopped the program. The difficulty is that the main "type 'a' repeatedly" wasn't happening.

Knowing bupkiss about Threading left me simply wondering. So I tried a couple modifications: «time.sleep(10)» became «time.sleep(2)» (to speed things up a bit); «print "a"» became «print "a",» (to keep things on a line); and «.start()» became «.run()» in the bottom 2 lines (because I figured 'Hey, anybody can mess up sometimes!') and, sure enough, running the module started producing a list of 'a's every 2 seconds.

But now typing in <CR> or b<CR> did nothing to stop or modify the printing.

Still confused. Any help, clarification, or discussion would be much appreciated.

Neal C.

Hello!

I don't know what IDLE makes with threads, you should save it in a file and run it in a console. It should print out an "a" every ten second. I tested it on linux. Try to lower the 10 seconds.

As you can see from the code, inputing b<enter> terminates the printa thread after the sleep. It does not terminates it immediately.

Please read the threading module documentation, and one of the countless tutorials.

If you want to can use the pyHook module
Download-http://sourceforge.net/project/showfiles.php?group_id=65529
Here is a program that will listen for any keystrokes really easily:

import pythoncom, pyHook 

def OnKeyboardEvent(event):
  print 'MessageName:',event.MessageName
  print 'Message:',event.Message
  print 'Time:',event.Time
  print 'Window:',event.Window
  print 'WindowName:',event.WindowName
  print 'Ascii:', event.Ascii, chr(event.Ascii)
  print 'Key:', event.Key
  print 'KeyID:', event.KeyID
  print 'ScanCode:', event.ScanCode
  print 'Extended:', event.Extended
  print 'Injected:', event.Injected
  print 'Alt', event.Alt
  print 'Transition', event.Transition
  print '---'

# return True to pass the event to other handlers
  return True

# create a hook manager
hm = pyHook.HookManager()
# watch for all mouse events
hm.KeyDown = OnKeyboardEvent
# set the hook
hm.HookKeyboard()
# wait forever
pythoncom.PumpMessages()

Oh you also need pythomcom, i think that is in the win32 package which you can get from here:
python.net/crew/mhammond/win32/Downloads.html
as i said i only think it is in there.

Is this hard?

I am introducing Python to my students and want to make a simple, interactive program that will, while it's running, 'listen' for any keyboard events. That is, I don't want to include an 'input' statement - that would pause execution till someone answered. I just want it to keep running, say, printing an 'a' on the screen every 10 seconds, until the user types a 'b'. Then printing a 'b' every 10 seconds till the user types in some other character...

It seems that this should not be hard; something with sys.stdin, perhaps. The hours I've spent on it are getting embarrassing.

I've fooled around with it and looked though books and the only solution I've come up with was to import pygame.py and use its event handling. This seems like massive overkill for what should be an easy matter.

I'm using IDLE with MacPython 2.5.1 on Mac OS 10.4.11

Thanks for any help on this problem.

Neal C.

Hi Neal,

I have the same problem. I need python to listen to keystrokes but also carry on its activity until it is triggered

Have you addressed the issue? Can you help me out,

Thanks,
Bryan

This article has been dead for over six months. Start a new discussion instead.