On my linux box, I use the following code. This is similar to the manual entry mentioned elsewhere but that code spins in a tight loop where this code doesn't and there are lots of odd corner cases that code doesn't account for that this code does.
def read_single_keypress():
"""Waits for a single keypress on stdin.
This is a silly function to call if you need to do it a lot because it has
to store stdin's current setup, setup stdin for reading single keystrokes
then read the single keystroke then revert stdin back after reading the
keystroke.
Returns the character of the key that was pressed (zero on
KeyboardInterrupt which can happen when a signal gets handled)
"""
import termios, fcntl, sys, os
fd = sys.stdin.fileno()
# save old state
flags_save = fcntl.fcntl(fd, fcntl.F_GETFL)
attrs_save = termios.tcgetattr(fd)
# make raw - the way to do this comes from the termios(3) man page.
attrs = list(attrs_save) # copy the stored version to update
# iflag
attrs[0] &= ~(termios.IGNBRK | termios.BRKINT | termios.PARMRK
| termios.ISTRIP | termios.INLCR | termios. IGNCR
| termios.ICRNL | termios.IXON )
# oflag
attrs[1] &= ~termios.OPOST
# cflag
attrs[2] &= ~(termios.CSIZE | termios. PARENB)
attrs[2] |= termios.CS8
# lflag
attrs[3] &= ~(termios.ECHONL | termios.ECHO | termios.ICANON
| termios.ISIG | termios.IEXTEN)
termios.tcsetattr(fd, termios.TCSANOW, attrs)
# turn off non-blocking
fcntl.fcntl(fd, fcntl.F_SETFL, flags_save & ~os.O_NONBLOCK)
# read a single keystroke
try:
ret = sys.stdin.read(1) # returns a single character
except KeyboardInterrupt:
ret = '\x03'
finally:
# restore old state
termios.tcsetattr(fd, termios.TCSAFLUSH, attrs_save)
fcntl.fcntl(fd, fcntl.F_SETFL, flags_save)
return ret
I don't know of a platform independent way of doing it, but under Windows, if you use the msvcrt module, you can use its getch function:
import msvcrt
c = msvcrt.getch()
print 'you entered', c
mscvcrt also includes the non-blocking kbhit() function to see if a key was pressed without waiting (not sure if there's a corresponding curses function). Under UNIX, there is the curses package, but not sure if you can use it without using it for all of the screen output. This code works under UNIX:
I am new to python and I was already thinking I am too stupid to reproduce the simplest suggestions made here.
It turns out, there's a pitfall one should know:
When a python-script is executed from IDLE, some IO-commands seem to behave completely different (as there is actually no terminal window).
Eg. msvcrt.getch is non-blocking and always returns $ff.
This has already been reported long ago (see e.g. https://bugs.python.org/issue9290 ) - and it's marked as fixed, somehow the problem seems to persist in current versions of python/IDLE.
So if any of the code posted above doesn't work for you, try running the script manually, and NOT from IDLE.
On my linux box, I use the following code. This is similar to the manual entry mentioned elsewhere but that code spins in a tight loop where this code doesn't and there are lots of odd corner cases that code doesn't account for that this code does.
Simply using
will cause a SyntaxError: expected EOF while parsing.
Simple fix use:
The python manual provides the following:
which can be rolled into your use case.
I don't know of a platform independent way of doing it, but under Windows, if you use the msvcrt module, you can use its getch function:
mscvcrt also includes the non-blocking kbhit() function to see if a key was pressed without waiting (not sure if there's a corresponding curses function). Under UNIX, there is the curses package, but not sure if you can use it without using it for all of the screen output. This code works under UNIX:
Note that curses.getch() returns the ordinal of the key pressed so to make it have the same output I had to cast it.
os.system seems to always invoke sh, which does not recognize the s and n options for read. However the read command can be passed to bash:
I am new to python and I was already thinking I am too stupid to reproduce the simplest suggestions made here. It turns out, there's a pitfall one should know:
When a python-script is executed from IDLE, some IO-commands seem to behave completely different (as there is actually no terminal window).
Eg. msvcrt.getch is non-blocking and always returns $ff. This has already been reported long ago (see e.g. https://bugs.python.org/issue9290 ) - and it's marked as fixed, somehow the problem seems to persist in current versions of python/IDLE.
So if any of the code posted above doesn't work for you, try running the script manually, and NOT from IDLE.