Python Curses Library Cheat Sheet

This cheat sheet provides a quick reference for the most common functions and patterns when using the curses library in Python. The Python interface simplifies the original C API by merging many functions into a single method with multiple argument forms.

Initialization & Cleanup

The safest way to start and end a curses application is to use the wrapper() function. It handles all the setup and error recovery automatically.

import curses

def main(stdscr):
    # Your curses code here
    pass

curses.wrapper(main)

Manual Initialization

If you need more control, you can initialize curses manually.

import curses

stdscr = curses.initscr()  # Initialize library and get the main window
curses.noecho()            # Don't echo typed characters to screen
curses.cbreak()            # Read input char-by-char (no Enter key needed)
stdscr.keypad(True)        # Enable special keys (like arrows) to be read

# ... application code ...

curses.nocbreak()
stdscr.keypad(False)
curses.echo()
curses.endwin()            # De-initialize library and restore terminal

Common Functions

  • initscr(): Initializes the library. Returns a window object representing the entire screen (stdscr).

  • wrapper(func): Initializes curses, calls func(stdscr), and restores the terminal on exit or exception.

  • endwin(): De-initializes curses and returns the terminal to its normal state.

  • cbreak() / nocbreak(): Enable/disable cbreak mode (character-by-character input).

  • echo() / noecho(): Enable/disable echoing of typed characters.

  • curs_set(visibility): Sets the cursor visibility. 0 for invisible, 1 for normal, 2 for very visible.

Color Support

To use colors, you must initialize color support and define color pairs.

# Enable color functionality
curses.start_color()
# Define a color pair
curses.init_pair(1, curses.COLOR_RED, curses.COLOR_WHITE)
# Get the attribute for the pair
RED_ON_WHITE = curses.color_pair(1)
stdscr.addstr("Red text on white background", RED_ON_WHITE)
  • start_color(): Must be called before any other color function.

  • init_pair(pair_number, fg, bg): Defines a color pair with a foreground and background color.

  • color_pair(pair_number): Returns the attribute value to use for a defined color pair.

Windows

A window is a rectangular area of the screen where you can display text.

Main Window

  • stdscr: The default window returned by initscr(), representing the entire screen.

Creating a New Window

  • newwin(height, width, begin_y, begin_x): Creates a new window at the specified position and size.

win = curses.newwin(10, 30, 5, 10) # Create a 10x30 window at (y=5, x=10)

Window Methods

  • addstr(y, x, string, attr): Display a string at a position. y and x are optional; if omitted, it uses the current cursor position.

  • getch(): Read a single character or special key code from the user.

  • refresh(): Update the physical terminal display to match the window’s buffer.

  • clear(): Clear the window.

  • box(): Draw a border around the window.

  • getmaxyx(): Returns the window’s height and width as a tuple (height, width).

Warning

The coordinate system in curses is row, column (y, x) with the top-left corner being (0,0). This is the opposite of the usual mathematical (x, y) order.

Key Handling

  • stdscr.keypad(True): Must be called to enable the reading of special keys like arrow keys.

  • stdscr.getch(): Reads a character or key. Returns an integer.

  • Special keys are defined as constants in the curses module, e.g., curses.KEY_UP, curses.KEY_DOWN, curses.KEY_LEFT, curses.KEY_RIGHT.

key = stdscr.getch()
if key == curses.KEY_UP:
    y -= 1
elif key == ord('q'):
    break

Common Pattern: Reusable Menu

A common pattern is creating a reusable function to generate selection menus.

def make_selection_menu(header, menu_options):
    def menu_function(stdscr):
        curses.curs_set(0)
        current_row = 0
        while True:
            stdscr.clear()
            stdscr.addstr(header + "\n", curses.A_BOLD)
            for idx, (label, _) in enumerate(menu_options):
                if idx == current_row:
                    stdscr.addstr(idx + 1, 2, label, curses.A_REVERSE)
                else:
                    stdscr.addstr(idx + 1, 2, label)
            stdscr.refresh()

            key = stdscr.getch()
            if key == curses.KEY_UP and current_row > 0:
                current_row -= 1
            elif key == curses.KEY_DOWN and current_row < len(menu_options) - 1:
                current_row += 1
            elif key == ord("\n"):  # Enter key
                menu_options[current_row][1](stdscr)
    return menu_function

Resources