We're back after a server migration that caused effbot.org to fall over a bit harder than expected. Expect some glitches.

How do I get a single keypress at a time?

For Windows, see:


For Unix variants: There are several solutions. It’s straightforward to do this using curses, but curses is a fairly large module to learn. Here’s a solution without curses:

import termios, fcntl, sys, os, select

fd = sys.stdin.fileno()

oldterm = termios.tcgetattr(fd)
newattr = oldterm[:]
newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO
termios.tcsetattr(fd, termios.TCSANOW, newattr)

oldflags = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK)

    while 1:
        r, w, e = select.select([fd], [], [])
        if r:
            c = sys.stdin.read(1)
            print "Got character", repr(c)
            if c == "q":
                break # quit
    termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)
    fcntl.fcntl(fd, fcntl.F_SETFL, oldflags)

You need the termios and the fcntl module for any of this to work, and I’ve only tried it on Linux, though it should work elsewhere. In this code, characters are read and printed one at a time, until the user presses ‘q’ to quit.

termios.tcsetattr() turns off stdin’s echoing and disables canonical mode. fcntl.fnctl() is used to obtain stdin’s file descriptor flags and modify them for non-blocking mode. The select module is then used to wait for incoming characters.

CATEGORY: library