Reputation: 662
I have a program that uses curses, and then returns to the main script for further processing. After it returns, my subsequent output to stdout does not appear until there's a large amount of it (e.g. thousands of bytes).
I've reduced the problem to a very simple program that fails reliably:
import curses
import time
curses.initscr()
curses.endwin()
print "Hello world!"
time.sleep(5)
If I comment out the two curses calls, the 'Hello world!' prints before the delay. If I put them in, it prints after the delay (when the script exits).
Upvotes: 4
Views: 1252
Reputation: 11
more clear way:
import sys
import curses
correct_stdout = sys.stdout # remember correct
curses.initscr()
curses.endwin()
sys.stdout = correct_stdout # restore correct
Upvotes: 1
Reputation: 70984
Alex beat me to it (he knew, I had to figure it out) but I wrote this nifty context manager that you might be able to use.
import curses
import time
import os
import sys
class CursesStdout(object):
def __enter__(self):
pass
def __exit__(self, *args):
sys.stdout = sys.__stdout__ = os.fdopen(sys.__stdout__.fileno(), 'w', 0)
with CursesStdout():
curses.initscr()
curses.endwin()
print "Hello world!"
time.sleep(2)
I modify sys.__stdout__
directly because when you look at the source in curses/__init__.py
you see that the initscr
function passes that file descriptor to the C code and so I store that to be reset to normal.
Upvotes: 1
Reputation: 54292
I have found that tis is system/library dependent. On my Windows machine (curses from http://www.lfd.uci.edu/~gohlke/pythonlibs/) it flushes and then sleeps, but on Linux it flushes after sleep. I think you can simply use: sys.stdout.flush()
like:
print "Hello world!"
sys.stdout.flush()
time.sleep(5)
(it may be better to make some kind of "print & flush" function)
Upvotes: 0
Reputation: 881567
The curses.endwin()
call "sets standard I/O back to normal"... which unfortunately means "buffered" (you could consider that a bug in curses
and file the bug on Python's tracker).
To ensure standard-output is unbuffered,
import os
sys.stdout = os.fdopen(0, 'w', 0)
(You can put the import os
at the start, or course; the reassignment of sys.stdout
is meant to go right after the endwin
call).
Upvotes: 3