I'm playing around a little with Python and curses.
When I run
import time
import curses
def main():
curses.initscr()
curses.cbreak()
for i in range(3):
time.sleep(1)
curses.flash()
pass
print( "Hello World" )
curses.endwin()
if __name__ == '__main__':
main()
if I wait all the way through, curses.endwin()
gets called so everything works out fine.
However, if I cut it short with Ctrl-C, curses.endwin()
never gets called so it screws up my terminal session.
What is the proper way to handle this situation? How can I make sure that no matter how I try to end/interrupt the program (e.g. Ctrl-C, Ctrl-Z), it doesn't mess up the terminal?
My advice: For testing purposes, call your script using a simple wrapper shell script; have the shell script perform a reset
command to bring your terminal settings back into a usable state:
#!/bin/sh
eval "$@"
stty -sane
reset
... call that as run.sh
and be happy. This should run your command almost exactly as your shell would if you entered the arguments as a command (more exactly if you wrap the arguments in hard quotes).
To ensure that your program will leave the terminal in a robust state, in the the face of uncaught exceptions and abnormal terminations ... either use the curses.wrapper()
method to call your top level entry point (probably main()
or whatever main_curses_ui()
you choose to implement) or wrap your code in your own sequence of curses.*
methods to restore cursor visibility, restore "cbreak" (canonical/cooked input) mode, restore the normal "echo" settings and whatever else you may have mucked with.
You can also use the Python: atexit Handlers to register all your clean-up actions. But there might still be cases where your code doesn't get called --- some sorts of non-catchable signals and any situation where os._exit() is invoked.
My little shell script wrapper should be fairly robust even in those cases.
You can:
try
/finally
block that calls curses.endwin()
signal
libraryatexit
library.The first option is probably the simplest for a basic case (if you're not running much code).
The second option is the most specific, if you want to do something special for Ctrl+C.
The last option is the most robust if you always want to do certain shutdown actions, no matter how your program is ending.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With