Sometimes it is more appropriate to read from keyboard without waiting for Enter to be codessed, for example, when choosing from a menu. The raw_input("Prompt String >") always waits for Enter, so a function similar to
getch()
in C is needed and there are some solutions for that in Python.
- There is getch() equivalent for Windows environment in library msvcrt:
import msvcrt
result = msvcrt.getch()
Funny thing is that the code works fine from command window (cmd.exe), but does not in IDLE: in IDLE it does not wait for a key and gives out '\xff' as the result.
In Linux the same can be done this way:
import sys, tty, termios
fd = sys.stdin.fileno()
# save original terminal settings
old_settings = termios.tcgetattr(fd)
# change terminal settings to raw read
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
# restore original terminal settings
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
print '\ncodessed char is \'' + ch +'\'\n'
Since the solution is system dependent some people propose a universal approach when program tries one implementation and if it fails - the other one, here is an example from ActiveState Code, Danny Yoo:
class _Getch:
"""Gets a single character from standard input.
Does not echo to the screen."""
def __init__(self):
try:
self.impl = _GetchWindows()
except ImportError:
self.impl = _GetchUnix()
def __call__(self): return self.impl()
class _GetchUnix:
def __init__(self):
import tty, sys
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()
getch = _Getch()
- Using TK library the following code works OK:
import Tkinter as tk
def keycodess(event):
if event.keysym == 'Escape':
root.destroy()
x = event.char
if x == "a":
print "A done"
elif x == "b":
print "B done"
elif x == "c":
print "C done"
elif x == "d":
print "D done"
else:
print x
root = tk.Tk()
print "a. Menu choice A"
print "b. Menu choice B"
print "c. Menu choice C"
print "d. Menu choice D"
root.bind_all('', keycodess)
# hiding the tk window
root.withdraw()
root.mainloop()
It works OK in Windows command window (cmd.exe), but in IDLE and Linux the line root.withdraw()
should be commented out - the code works OK while the root window is in focus. This kind of examples you can find here.
- Curses library has its own getch implementation. I did not check it, just would like to mention for the record.
If you know any other solutions - I'd love to here from you about them!
0 comments:
Post a Comment