In the code you've posted, the context manager will yield only once when the with
is executed. So the code has to execute first (all 15 seconds of it) and all the code output is stored within the StringIO
object. Hence, with such code, you cannot obtain output as it is written.
If you want to output on the fly, you need to provide your own file
-like class instead of StringIO
and override the write
method. For example (example only, very quick and dirty code):
import sys
import StringIO
import contextlib
class Proxy(object):
def __init__(self,stdout,stringio):
self._stdout = stdout
self._stringio = stringio
def __getattr__(self,name):
if name in ('_stdout','_stringio','write'):
object.__getattribute__(self,name)
else:
return getattr(self._stringio,name)
def write(self,data):
self._stdout.write(data)
self._stringio.write(data)
@contextlib.contextmanager
def stdoutIO(stdout=None):
old = sys.stdout
if stdout is None:
stdout = StringIO.StringIO()
sys.stdout = Proxy(sys.stdout,stdout)
yield sys.stdout
sys.stdout = old
code = """
import time
i = [0,1,2]
for j in i :
print j
time.sleep(5)
"""
with stdoutIO() as s:
exec code
print "out:", s.getvalue()
which outputs:
0
1
2
out: 0
1
2
The first three lines are printed at 5 seconds intervals. The last three in one go at the end.