views:

338

answers:

1

Where do stdout and stderr go when curses is active?

import curses, sys

def test_streams():
    print "stdout"
    print >>sys.stderr, "stderr"

def curses_mode(stdscr):
    test_streams()

test_streams()
curses.wrapper(curses_mode)

Actual output is

stdout
stderr

Update0

Expected output is

stdout
stderr
stdout
stderr

entering, and then exiting curses mode with no change to the final text shown in the terminal.

+2  A: 

Activating curses saves the terminal text screen's current contents and clears said screen; exiting curses restores the screen's contents (tossing away whatever's been put on screen during the reign of curses itself). Try with this variant of your code and you'll see better what's happening:

import curses, sys, time

def test_streams(wot):
    print wot, "stdout"
    print >>sys.stderr, wot, "stderr"

def curses_mode(stdscr):
    test_streams("wrap")
    time.sleep(1.0)

test_streams("before")
curses.wrapper(curses_mode)
test_streams("after")

You'll note the wrap stderr on the screen for a second (during the sleep) -- it's overwritten the stdout part -- then it disappears and you see the four before and after lines on the now-quiescent screen (you can add other sleeps to follow what's happening in even more details, if you care).

Alex Martelli
what can you say about where the output on those streams is going tho? from what I can tell, stderr is "ignored", and stdout is interleaved with terminal instructions, i'm guessing that if you dump to either of them it's terminal dependent on what the data does/where it goes?
Matt Joiner
@Matt, on both Mac and Linux with the code as given above I see "wrap stderr" for a second on an otherwise empty string, so I don't know why you say stderr is "ignored". They both shd be going where they were going before, i.e /dev/tty (you may have to flush them as their buffering state may have been temporarily altered, depending on your OS and libraries).
Alex Martelli
NB: the curses library doesn't save the current screen contents; it switches by default to the alternate screen (terminal terminology :) *if* such a beast exists, and switches back to the normal screen on exit. If the terminal (actually, the terminfo data) has no alternate screen, curses just clears the screen. Compare a curses program running under e.g. `/usr/bin/xterm` (or some recent terminal) and `/usr/bin/screen` (where the virtual terminal "screen" offers no alternate screen). I just wrote an awfully messed-up comment, but I can't do otherwise :)
ΤΖΩΤΖΙΟΥ
The terminfo entries that switch the screens are: `smcup` (`^[[?1049h` typically) and `rmcup` (`^[[?1049l`). One can manually switch between screens by issuing `tput smcup` and `tput rmcup` to the shell.
ΤΖΩΤΖΙΟΥ