views:

157

answers:

2

I am working in the Google Application Engine environment where I am loading doctests and python code from strings to test Python homework assignments. My basic implementation (Provided by Alex Martelli) appears to work for all of my problems except for those containing the print statement. Something seems to go wrong when I attempt to execute the print command within GAE.

How would you modify this example to capture anything written out by the print statement?

#This and most other code works
class X(object): pass

x=X()
exec 'a=23' in vars(x)


#This throws an error. 
class X(object): pass

x=X()
exec 'print 23' in vars(x)
+2  A: 

For this problem I like to capture the string output directly. Inside your function I would use something like:

import StringIO, sys

# create file-like string to capture output
codeOut = StringIO.StringIO()

# capture output and errors
sys.stdout = codeOut
err = ''

try   : 
    exec code in code_namespace
except Exception:
    err = str(sys.exc_info()[1])

And finish with:
# restore stdout and stderr
sys.stdout = sys.__stdout__

To restore normal the function of print.

Hooked
+4  A: 

I think Hooked has the right answer, but I think you'd be better off storing the value of sys.stdout before you modify it and restoring that value afterwards rather than restoring sys.__stdout__ because (I think) the App Engine runtime tinkers with sys.stdout in its own way.

That leaves you with something like

import StringIO
import sys

# Store App Engine's modified stdout so we can restore it later
gae_stdout = sys.stdout

# Redirect stdout to a StringIO object
new_stdout = StringIO.StringIO()
sys.stdout = new_stdout

# Run your code here, however you're doing that

# Get whatever was printed to stdout using the `print` statement (if necessary)
printed = new_stdout.getvalue()

# Restore App Engine's original stdout
sys.stdout = gae_stdout
Will McCutchen