2026-01-17
When working with ncurses, bugs have a little extra kick. Instead of just crashing your program, you can mess up your terminal even after the program ends!
For a quick (and forced) example:
import curses
stdscr = curses.initscr()
raise RuntimeError("oops!") # Some error in your code
curses.endwin()
This code will fail, and after it fails, the terminal will print newlines wrong. curses sets some terminal options in initscr and needs to reset them with endwin. If your code crashes, that cleanup never happens, and your terminal settings don't get restored.
endwin is a great use case for a finally block.
import curses
try:
stdscr = curses.initscr()
raise RuntimeError("oops!") # Some error in your code
finally:
curses.endwin()
Now, If the code crashes, Python will make sure to clean up after itself and restore the terminal state.
Python offers curses.wrapper to automatically handle setup and cleanup for you. The code for it is pretty much just a try...finally block that also covers echo, cbreak, and keypad functions.
import curses
def main(stdscr):
stdscr.clear()
stdscr.addstr("Hello!")
stdscr.refresh()
curses.napms(1_000)
curses.wrapper(main)