0

I'm trying to create a python script that will do a load of computation while continually updating a curses interface (for the purposes of this question, just imagine it's a progress bar). The code is structured like this:

while notDone:
     compute()
     updateScreen()

I'd like to allow the user to hit a button to quit the program, but the only way I know how with curses is like this:

while notDone:
     compute()
     updateScreen()
     c = screen.getch()
     if c == "q": break

Which won't work, because it means that after each iteration, the script will wait for the user to press a key. I need the keypress to work like Ctrl+C does in most python scripts - it interrupts the script and kills it. In fact, a way to just capture a KeyboardInterrupt exception and handle it like normal would work just fine.

Jack M
  • 4,769
  • 6
  • 43
  • 67

2 Answers2

1

Curses allows input to be blocking, non-blocking, or "half-blocking" (where there's a wait, but only of limited duration). Nothing fancy needed, just call nodelay(). In this mode, getch() will return ERR if no input is waiting. (You should probably also call cbreak() before nodelay(), just to be on the safe side.)

William McBrine
  • 2,166
  • 11
  • 7
0

You can call screen.getch() in another thread, and make it raise KeyboardInterrupt in the main thread. Here is how to raise exceptions in other threads in CPython: https://gist.github.com/liuw/2407154

I don't know how stable this is in corner cases, but it's worth a try.

Alternatively, you can also install a sys.settrace to the main thread which would raise the exception when the other thread has finished reading a character, but sys.settrace makes your main thread much slower.

pts
  • 80,836
  • 20
  • 110
  • 183