Explain Codes LogoExplain Codes Logo

How to read a single character from the user?

python
input-output
cross-platform
best-practices
Anton ShumikhinbyAnton Shumikhin·Feb 20, 2025
TLDR

No need to beat around the bush. Here's a quick and easy cross-platform way to catch that rogue character in Python:

def get_char(): try: import msvcrt # Getting characters the Windows way return msvcrt.getch() except ImportError: # So, you're not on Windows? No problem! import sys, tty, termios # Beware! Untamed terminal settings ahead! fd = sys.stdin.fileno() old_settings = termios.tcgetattr(fd) try: # Set terminal raw, do magic tty.setraw(sys.stdin.fileno()) return sys.stdin.read(1) finally: # Restore terminal. Nothing to see here. termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) char = get_char() # Congratulations! You captured a wild character. print(f'You entered: {char}')

This module has got your back whether you're a Windows or a Unix user. It determines which OS you're using and then, either msvcrt.getch() for Windows, or the mighty tty and termios modules for Unix-like systems are brought into play to read that character without needing an enter press.

The mighty OS jungle: understanding the terrain

Not all operating systems are created equal. They have their unique ways to handle input, and that's fine. We just need to navigate our way around them.

Using try-except for cross-platform compatibility

With the dynamic try-except mechanism, the script attempts to import msvcrt (module widely known amongst Windows users) first. If it fails (signaling that we're not on a Windows system), tty and termios are imported instead. It's like asking for a cappuccino, and if they don't have it, you'll have an espresso.

Activating the right tool for the right OS, the code works its way around different ways to read un-buffered primary character input. It dynamically sets the terminal to raw mode and reads the input character by character, ensuring you have the best experience whether on Windows or Unix.

Handling the Terminal settings: the terminal's day out

The terminal's settings are a big part of how input and output operations are handled. By altering these settings even for a brief moment, the get_char() function gets exactly what it needs.

Remember gentlemanliness? The script returns all terminal settings untouched once it's done. This finally clause ensures we leave no mess behind, or in terminal lingo, no altered settings.

Libraries: assisting with the art of character catching

If you want a purpose-built tool which handles single character inputs, the readchar library offers a quite convenient method. Care to catch some special keys? Fancy some platform-specific keycodes? readchar has got you covered.

Unblocked, uninterrupted: non-blocking operation mode

You know what's better than catching characters? Catching them without being held up!

By using os, sys, termios, fcntl combined, you can set up an environment that allows non-blocking input mode. Such an approach proves beneficial if your application cannot afford to stop and wait for the user's input.

Referencing battle-tested resources

  1. sys — System-specific parameters and functions — Python 3.12.2 documentation — The official guidebook from Python sys.stdin.
  2. getch · PyPI — The treasure map to the Python getch module.
  3. Basic Input, Output, and String Formatting in Python – Real PythonReal Python gives an intensive session on in-JPython kung-fu.
  4. GNU Readline Library — Get to know your line-editing neighbors around Python with GNU Readline.
  5. readchar · PyPI — A ready-to-use toolkit for reading single characters in Python.
  6. #18 Python Tutorial for Beginners | User input in Python | Command Line Input - YouTubeLights, camera, action! See this Python feature film on input/output.