Home > Article > Backend Development > How do I detect keyboard input in a Python script running from the terminal?
<code class="python">typedString = raw_input()</code>
<code class="python">class _Getch: """Gets a single character from standard input. Does not echo to the screen. From http://code.activestate.com/recipes/134892/""" def __init__(self): try: self.impl = _GetchWindows() except ImportError: try: self.impl = _GetchMacCarbon() except(AttributeError, ImportError): self.impl = _GetchUnix() def __call__(self): return self.impl() class _GetchUnix: def __init__(self): import tty, sys, termios # import termios now or else you'll get the Unix version on the Mac def __call__(self): import sys, tty, termios fd = sys.stdin.fileno() old_settings = termios.tcgetattr(fd) try: tty.setraw(sys.stdin.fileno()) ch = sys.stdin.read(1) finally: termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) return ch class _GetchWindows: def __init__(self): import msvcrt def __call__(self): import msvcrt return msvcrt.getch() class _GetchMacCarbon: """ A function which returns the current ASCII key that is down; if no ASCII key is down, the null string is returned. The page http://www.mactech.com/macintosh-c/chap02-1.html was very helpful in figuring out how to do this. """ def __init__(self): import Carbon Carbon.Evt #see if it has this (in Unix, it doesn't) def __call__(self): import Carbon if Carbon.Evt.EventAvail(0x0008)[0]==0: # 0x0008 is the keyDownMask return '' else: # # The event contains the following info: # (what,msg,when,where,mod)=Carbon.Evt.GetNextEvent(0x0008)[1] # # The message (msg) contains the ASCII char which is # extracted with the 0x000000FF charCodeMask; this # number is converted to an ASCII character with chr() and # returned # (what,msg,when,where,mod)=Carbon.Evt.GetNextEvent(0x0008)[1] return chr(msg & 0x000000FF) def getKey(): inkey = _Getch() import sys for i in xrange(sys.maxint): k=inkey() if k<>'':break return k</code>
Callbacks have not yet been implemented.
Callbacks have not yet been implemented.
Windows:
<code class="python">import threading from win32api import STD_INPUT_HANDLE from win32console import GetStdHandle, KEY_EVENT, ENABLE_ECHO_INPUT, ENABLE_LINE_INPUT, ENABLE_PROCESSED_INPUT class KeyAsyncReader(): def __init__(self): self.stopLock = threading.Lock() self.stopped = True self.capturedChars = "" self.readHandle = GetStdHandle(STD_INPUT_HANDLE) self.readHandle.SetConsoleMode(ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT|ENABLE_PROCESSED_INPUT) def startReading(self, readCallback): self.stopLock.acquire() try: if not self.stopped: raise Exception("Capture is already going") self.stopped = False self.readCallback = readCallback backgroundCaptureThread = threading.Thread(target=self.backgroundThreadReading) backgroundCaptureThread.daemon = True backgroundCaptureThread.start() except: self.stopLock.release() raise self.stopLock.release() def backgroundThreadReading(self): curEventLength = 0 curKeysLength = 0 while True: eventsPeek = self.readHandle.PeekConsoleInput(10000) self.stopLock.acquire() if self.stopped: self.stopLock.release() return self.stopLock.release() if len(eventsPeek) == 0: continue if not len(eventsPeek) == curEventLength: if self.getCharsFromEvents(eventsPeek[curEventLength:]): self.stopLock.acquire() self.stopped = True self.stopLock.release() break curEventLength = len(eventsPeek) def getCharsFromEvents(self, eventsPeek): callbackReturnedTrue = False for curEvent in eventsPeek: if curEvent.EventType == KEY_EVENT: if ord(curEvent.Char) == 0 or not curEvent.KeyDown: pass else: curChar = str(curEvent.Char) if self.readCallback(curChar) == True: callbackReturnedTrue = True return callbackReturnedTrue def stopReading(self): self.stopLock.acquire() self.stopped = True self.stopLock.release()</code>
<code class="python">global isWindows isWindows = False try: from win32api import STD_INPUT_HANDLE from win32console import GetStdHandle, KEY_EVENT, ENABLE_ECHO_INPUT, ENABLE_LINE_INPUT, ENABLE_PROCESSED_INPUT isWindows = True except ImportError as e: import sys import select import termios class KeyPoller(): def __enter__(self): global isWindows if isWindows: self.readHandle = GetStdHandle(STD_INPUT_HANDLE) self.readHandle.SetConsoleMode(ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT|ENABLE_PROCESSED_INPUT) self.curEventLength = 0 self.curKeysLength = 0 self.capturedChars = [] else: # Save the terminal settings self.fd = sys.stdin.fileno() self.new_term = termios.tcgetattr(self.fd) self.old_term = termios.tcgetattr(self.fd) # New terminal setting unbuffered self.new_term[3] = (self.new_term[3] & ~termios.ICANON & ~termios.ECHO) termios.tcsetattr(self.fd, termios.TCSAFLUSH, self.new_term) return self def __exit__(self, type, value, traceback): if isWindows: pass else: termios.tcsetattr(self.fd, termios.TCSAFLUSH, self.old_term) def poll(self): if isWindows: if not len(self.capturedChars) == 0: return self.capturedChars.pop(0) eventsPeek = self.readHandle.PeekConsoleInput(10000) </code>
The above is the detailed content of How do I detect keyboard input in a Python script running from the terminal?. For more information, please follow other related articles on the PHP Chinese website!