Skip to main content

Disabling terminal echo in Python

I recently wanted to disable echoing of the terminal in Python. When googling for that you quickly run into recommendations on getpass.getpass. Sadly, in my case of sort-of-non-blocking I/O it didn't fit. It needed something to fit with this:

def read_line(timeout, timeout_func):
    ready_to_read, _, _ = select.select([sys.stdin], [], [],
                                        timeout)
    if ready_to_read:
        return sys.stdin.readline().rstrip()
    else:
        timeout_func()
        return ''

So I needed a way to just disable terminal echo. This is what I came up with:

import termios

def enable_echo(fd, enabled):
    (iflag, oflag, cflag, lflag, ispeed, ospeed, cc) \
        = termios.tcgetattr(fd)

    if enabled:
        lflag |= termios.ECHO
    else:
        lflag &= ~termios.ECHO

    new_attr = [iflag, oflag, cflag, lflag, ispeed, ospeed, cc]
    termios.tcsetattr(fd, termios.TCSANOW, new_attr)

Also, I added this code to restore the terminal on progam exit:

import atexit
atexit.register(enable_echo, sys.stdin.fileno(), True)