python: get the print output in an exec statement

Since Python 3.4 there is a solution is the stdlib: https://docs.python.org/3/library/contextlib.html#contextlib.redirect_stdout

from io import StringIO
from contextlib import redirect_stdout

f = StringIO()
with redirect_stdout(f):
    help(pow)
s = f.getvalue()

In older versions you can write a context manager to handle replacing stdout:

import sys
from io import StringIO
import contextlib

@contextlib.contextmanager
def stdoutIO(stdout=None):
    old = sys.stdout
    if stdout is None:
        stdout = StringIO()
    sys.stdout = stdout
    yield stdout
    sys.stdout = old

code = """
i = [0,1,2]
for j in i :
    print j
"""
with stdoutIO() as s:
    exec(code)

print("out:", s.getvalue())

You can redirect the standard output to a string for the duration of the exec call:

Python2

import sys
from cStringIO import StringIO

code = """
i = [0,1,2]
for j in i:
    print(j)
"""

old_stdout = sys.stdout
redirected_output = sys.stdout = StringIO()
exec(code)
sys.stdout = old_stdout

print(redirected_output.getvalue())

Python3

import sys
from io import StringIO

code = """
i = [0,1,2]
for j in i:
    print(j)
"""

old_stdout = sys.stdout
redirected_output = sys.stdout = StringIO()
exec(code)
sys.stdout = old_stdout

print(redirected_output.getvalue())

Here is Py3-friendly version of @Jochen's answer. I also added try-except clause to recover in case of errors in the code.

import sys
from io import StringIO
import contextlib

@contextlib.contextmanager
def stdoutIO(stdout=None):
    old = sys.stdout
    if stdout is None:
        stdout = StringIO()
    sys.stdout = stdout
    yield stdout
    sys.stdout = old

code = """
i = [0,1,2]
for j in i :
    print(j)
"""
with stdoutIO() as s:
    try:
        exec(code)
    except:
        print("Something wrong with the code")
print("out:", s.getvalue())