You really have two choices. One you can leave curses mode, execute your program, then resume curses. Two, you can execute your program asynchronously, parse its output and write it to the screen.
The good news on the first option is that you don't actually need to write any fancy save_state / load_state methods for the ui. Curses does this for you. Here's a simple example to show my point
import curses, time, subprocess
class suspend_curses():
"""Context Manager to temporarily leave curses mode"""
def __enter__(self):
curses.endwin()
def __exit__(self, exc_type, exc_val, tb):
newscr = curses.initscr()
newscr.addstr('Newscreen is %s\n' % newscr)
newscr.refresh()
curses.doupdate()
def main(stdscr):
stdscr.addstr('Stdscreen is %s\n' % stdscr)
stdscr.refresh()
time.sleep(1)
with suspend_curses():
subprocess.call(['ls'])
time.sleep(1)
stdscr.refresh()
time.sleep(5)
curses.wrapper(main)
If you run the example, you will notice that the screen created by curses.wrapper
and the one created in curses.initscr
when resuming are the same object. That is, the window returned by curses.initscr
is a singleton. This lets us exit curses and resume like above without having to update each widget's self.screen
references each time.
The second option is much more involved but also much more flexible. The following is just to represent the basic idea.
class procWidget():
def __init__(self, stdscr):
# make subwindow / panel
self.proc = subprocess.Popen(my_args, stdout=subprocess.PIPE)
def update(self):
data = self.proc.stdout.readline()
# parse data as necessary
# call addstr() and refresh()
Then somewhere in your program you will want to call update
on all your procWidgets on a timer. This gives you the option of making your subwindow any size/place so you can have as many procWidgets as will fit. You will have to add some handling for when the process terminates and other similar events of course.