views:

8168

answers:

6

How do I execute a string containing Python code in Python?

+1  A: 

Use eval.

Pablo Santa Cruz
A: 

Check out eval:

x = 1
print eval('x+1')
->2
ryeguy
+1  A: 

In the example a string is executed as code using the exec function.

import sys
import StringIO

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

code = """
def f(x):
    x = x + 1
    return x

print 'This is my output.'
"""

# capture output and errors
sys.stdout = codeOut
sys.stderr = codeErr

exec code

# restore stdout and stderr
sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__

print f(4)

s = codeErr.getvalue()

print "error:\n%s\n" % s

s = codeOut.getvalue()

print "output:\n%s" % s

codeOut.close()
codeErr.close()
hekevintran
Why did you post this?
ryeguy
A: 

The most logical solution would be to use the built-in eval() function .Another solution is to write that string to a temporary python file and execute it.

John T
+16  A: 

For statements, use exec

ie.

>>> mycode = 'print "hello world"'
>>> exec mycode
Hello world

When you need the value of an expression, use eval. eg

>>> x = eval("2+2")
>>> x
4

However, the first step should be to ask yourself if you really need to. Executing code should generally be the position of last resort: It's slow, ugly and dangerous if it can contain user-entered code. You should always look at alternatives first, such as higher order functions, to see if these can better meet your needs.

Brian
A: 

Just a response to hekevintran's advice. I don't think you can redirect stderr/stdout with exec. See this page http://docs.python.org/library/sys.html?highlight=stderr#sys.stderr

it says "Changing these objects doesn’t affect the standard I/O streams of processes executed by os.popen(), os.system() or the exec*() family of functions in the os module."

one approach I am experimenting with is:

try: result=eval(user_input) except: exec(user_input)

eval returns a value, but doesn't work for all commands. exec works for all, but doesn't return a value. Still trying to figure out a way around this