486

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


Do not ever use eval (or exec) on data that could possibly come from outside the program in any form. It is a critical security risk. You allow the author of the data to run arbitrary code on your computer. If you are here because you want to create multiple variables in your Python program following a pattern, you almost certainly have an XY problem. Do not create those variables at all - instead, use a list or dict appropriately.

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
hekevintran
  • 22,822
  • 32
  • 111
  • 180
  • 14
    The correct answer, of course, is almost always “don't!”. – bobince Mar 31 '09 at 16:28
  • Hi, hekevintran! Would you consider to accept an answer? [allan's one](https://stackoverflow.com/a/14926430/2989289) could help me in my search – artu-hnrq May 02 '20 at 03:21

14 Answers14

458

For statements, use exec(string) (Python 2/3) or exec string (Python 2):

>>> my_code = 'print("hello world")'
>>> exec(my_code)
Hello world

When you need the value of an expression, use eval(string):

>>> 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.

Michael Currie
  • 13,721
  • 9
  • 42
  • 58
Brian
  • 116,865
  • 28
  • 107
  • 112
  • 1
    but how about the scope of the code executed by 'exec'? is it nested? – jondinham Mar 06 '12 at 10:24
  • 30
    A common case where someone wants to use 'exec' is something like `if s=='foo': x.foo = 42 elif s=='bar': x.bar = 42` etc, which they may then write as `exec ("x.%s = 42" % s)`. For this common case (where you only need to access an object's attribute that is stored in a string), there is a much faster, cleaner and safer function `getattr`: just write `getattr(x, s) = 42` to mean the same thing. – ShreevatsaR Apr 19 '12 at 19:18
  • 8
    How is exec any slower than the python interpreter? – Cris Stringfellow Feb 06 '13 at 16:36
  • 7
    @ShreevatsaR don't you mean `setattr(x, s, 42)`? I tried `getattr(x, 2) = 42` and it failed with `can't assign to function call: , line 1` – Tanner Semerad Oct 11 '13 at 17:44
  • 8
    @Tanner: Hmm. Yes indeed `setattr(x, s, 42)` is the right syntax. Surprised it took so long for that error to be caught. Anyway, the point is that `getattr` and `setattr` are an alternative to `exec` when all you want is to get an arbitrary member, looked up by string. – ShreevatsaR Oct 11 '13 at 19:01
  • My usecase is allowing some debugging/admin access to a web service. – Sergey Orshanskiy Oct 02 '14 at 19:24
  • One legitimate use of the exec function I have found is when I define custom magics in iPython Notebook. The input to the magic function is a string representation of the code in the line or cell of the magic. After doing whatever "magic" the magic should do, you need to execute the code. – Gordon Bean Dec 03 '14 at 18:19
  • 1
    @CrisStringfellow slower because it has to recompile every time – Erik Aronesty Jul 08 '15 at 20:29
  • I don't recommend using exec() function because it cannot change local variables, which could cause faults. Please see https://www.sololearn.com/Discuss/1336429/exec-doesn-t-work-with-local-variables-in-function-python f – Z.LI Apr 26 '21 at 14:41
85

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
  • 22,822
  • 32
  • 111
  • 180
39

eval and exec are the correct solution, and they can be used in a safer manner.

As discussed in Python's reference manual and clearly explained in this tutorial, the eval and exec functions take two extra parameters that allow a user to specify what global and local functions and variables are available.

For example:

public_variable = 10

private_variable = 2

def public_function():
    return "public information"

def private_function():
    return "super sensitive information"

# make a list of safe functions
safe_list = ['public_variable', 'public_function']
safe_dict = dict([ (k, locals().get(k, None)) for k in safe_list ])
# add any needed builtins back in
safe_dict['len'] = len

>>> eval("public_variable+2", {"__builtins__" : None }, safe_dict)
12

>>> eval("private_variable+2", {"__builtins__" : None }, safe_dict)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
NameError: name 'private_variable' is not defined

>>> exec("print \"'%s' has %i characters\" % (public_function(), len(public_function()))", {"__builtins__" : None}, safe_dict)
'public information' has 18 characters

>>> exec("print \"'%s' has %i characters\" % (private_function(), len(private_function()))", {"__builtins__" : None}, safe_dict)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
NameError: name 'private_function' is not defined

In essence you are defining the namespace in which the code will be executed.

Sergey Orshanskiy
  • 6,794
  • 1
  • 46
  • 50
alan
  • 3,246
  • 1
  • 32
  • 36
  • 15
    It is not possible to make eval safe: [Eval really is dangerous](http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html). If you take code from me and eval it, I can segfault your Python program. Game over. – Ned Batchelder Feb 18 '13 at 04:20
  • @NedBatchelder: this is no more dangerous than anything. in your link `rm /rf` is mentioned. so should we say that bash is dangerous because we can also do that ? the only problem is elevation attacks. But we care not about this if the script is not a remote service (i.e. if it is just something executed by you). – v.oddou Jan 13 '15 at 03:41
  • 5
    @v.oddou I was responding to alan's statement, "eval and exec .. can be used in a safe manner." This is false. If someone said, "bash can be used in a safe manner," that would also be false. Bash is dangerous. It is a necessary danger, but dangerous nevertheless. Claiming that eval can be made safe is simply wrong. – Ned Batchelder Jan 13 '15 at 15:10
  • 1
    @NedBatchelder yes indeed. and the link you point to is good material. with power comes responsibility, so the point is simply to be aware of the potential power of eval. and if we decide that power=danger. – v.oddou Jan 14 '15 at 02:08
  • 4
    @NedBatchelder Many pieces of code written in Python can be dangerous as well, but why are you assuming that `eval` or `exec` are intended to be used as `exec(input("Type what you want"))`? There are many cases where a program may write a procedure or a function as a result of a computation; resulting functions will be as safe and as fast (once evaluated) as any other part of a good and well-written program. _An unsafe program containing `exec` is not more dangerous than an unsafe program doing the damage by itself as `exec` doesn't give any new privilege to the program._ – Thomas Baruchel Nov 16 '16 at 10:46
  • 1
    @ThomasBaruchel again, my point is to counter the notion that eval or exec can be made safe. In particular, this answer claims that controlling the globals and locals will make it possible to use them safely. That is false. Any time you use exec and eval, you have to know precisely what code is being executed. If you don't, then you are open to dangerous operations. – Ned Batchelder Nov 16 '16 at 23:10
23

Remember that from version 3 exec is a function!
so always use exec(mystring) instead of exec mystring.

Remi Guan
  • 21,506
  • 17
  • 64
  • 87
bheks
  • 293
  • 3
  • 2
16

Avoid exec and eval

Using exec and eval in Python is highly frowned upon.

There are better alternatives

From the top answer (emphasis mine):

For statements, use exec.

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

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.

From Alternatives to exec/eval?

set and get values of variables with the names in strings

[while eval] would work, it is generally not advised to use variable names bearing a meaning to the program itself.

Instead, better use a dict.

It is not idiomatic

From http://lucumr.pocoo.org/2011/2/1/exec-in-python/ (emphasis mine)

Python is not PHP

Don't try to circumvent Python idioms because some other language does it differently. Namespaces are in Python for a reason and just because it gives you the tool exec it does not mean you should use that tool.

It is dangerous

From http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html (emphasis mine)

So eval is not safe, even if you remove all the globals and the builtins!

The problem with all of these attempts to protect eval() is that they are blacklists. They explicitly remove things that could be dangerous. That is a losing battle because if there's just one item left off the list, you can attack the system.

So, can eval be made safe? Hard to say. At this point, my best guess is that you can't do any harm if you can't use any double underscores, so maybe if you exclude any string with double underscores you are safe. Maybe...

It is hard to read and understand

From http://stupidpythonideas.blogspot.it/2013/05/why-evalexec-is-bad.html (emphasis mine):

First, exec makes it harder to human beings to read your code. In order to figure out what's happening, I don't just have to read your code, I have to read your code, figure out what string it's going to generate, then read that virtual code. So, if you're working on a team, or publishing open source software, or asking for help somewhere like StackOverflow, you're making it harder for other people to help you. And if there's any chance that you're going to be debugging or expanding on this code 6 months from now, you're making it harder for yourself directly.

Community
  • 1
  • 1
Caridorc
  • 6,222
  • 2
  • 31
  • 46
  • 1
    "my best guess is that you can't do any harm if you can't use any double underscores" - You could construct a string containing double underscores, and then call eval that string. – Stanley Bak Oct 11 '16 at 16:11
  • 1
    good advice, unless you are writing a code generator, or job runner or similar ... which most people here are probably doing. – Erik Aronesty May 03 '19 at 12:59
  • 1
    I have to import a relative path from a config-file (`cfg.yaml`): `reldir : ../my/dir/ `, and `reldir = cfg[reldir]`. However, as this python code shall run on both Windows and Linux, I need this to adjust to the different operating systems path dividers; either `\\ ` or `/`. So I use `reldir : os.path.join('..','my','dir')` in the config file. But this only results in `reldir` being this literal string, not being evaluated, so I cannot open a file in `reldir`. Do you have a suggestion? – Marie. P. Mar 11 '20 at 14:18
  • Uhm, no. These are highly pythonic. What do you think a REPL is? – Blaze Oct 17 '20 at 20:30
14

eval() is just for expressions, while eval('x+1') works, eval('x=1') won't work for example. In that case, it's better to use exec, or even better: try to find a better solution :)

Jérôme Verstrynge
  • 57,710
  • 92
  • 283
  • 453
LGB
  • 149
  • 1
  • 2
14

It's worth mentioning that exec's brother exists as well, called execfile, if you want to call a Python file. That is sometimes good if you are working in a third party package which have terrible IDE's included and you want to code outside of their package.

Example:

execfile('/path/to/source.py')

or:

exec(open("/path/to/source.py").read())

CrazyChucky
  • 3,263
  • 4
  • 11
  • 25
user1767754
  • 23,311
  • 18
  • 141
  • 164
9

You accomplish executing code using exec, as with the following IDLE session:

>>> kw = {}
>>> exec( "ret = 4" ) in kw
>>> kw['ret']

4
octopusgrabbus
  • 10,555
  • 15
  • 68
  • 131
gus
  • 99
  • 1
  • 2
8

As the others mentioned, it's "exec" ..

but, in case your code contains variables, you can use "global" to access it, also to prevent the compiler to raise the following error:

NameError: name 'p_variable' is not defined

exec('p_variable = [1,2,3,4]')
global p_variable
print(p_variable)
Minions
  • 5,104
  • 5
  • 50
  • 91
6

I tried quite a few things, but the only thing that worked was the following:

temp_dict = {}
exec("temp_dict['val'] = 10") 
print(temp_dict['val'])

output:

10

paul-shuvo
  • 1,874
  • 4
  • 33
  • 37
5

Use eval.

Pablo Santa Cruz
  • 176,835
  • 32
  • 241
  • 292
5

Check out eval:

x = 1
print eval('x+1')
->2
ryeguy
  • 65,519
  • 58
  • 198
  • 260
1

Ok .. I know this isn't exactly an answer, but possibly a note for people looking at this as I was. I wanted to execute specific code for different users/customers but also wanted to avoid the exec/eval. I initially looked to storing the code in a database for each user and doing the above.

I ended up creating the files on the file system within a 'customer_filters' folder and using the 'imp' module, if no filter applied for that customer, it just carried on

import imp


def get_customer_module(customerName='default', name='filter'):
    lm = None
    try:
        module_name = customerName+"_"+name;
        m = imp.find_module(module_name, ['customer_filters'])
        lm = imp.load_module(module_name, m[0], m[1], m[2])
    except:
        ''
        #ignore, if no module is found, 
    return lm

m = get_customer_module(customerName, "filter")
if m is not None:
    m.apply_address_filter(myobj)

so customerName = "jj" would execute apply_address_filter from the customer_filters\jj_filter.py file

Brian
  • 186
  • 2
  • 11
1

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
  • 23,735
  • 11
  • 56
  • 82