Skip to content

Dynamic Execution: eval, exec, & compile

Most programs are static: the code you write is the code that runs. However, Python is dynamic enough to create and execute code at runtime. This is extremely powerful for building things like template engines, math expression parsers, or plugin systems.

But with great power comes extreme danger—improper use of dynamic execution is the leading cause of security vulnerabilities.


eval(expression) parses a single Python expression, executes it, and returns the result.

x = 10
result = eval("x * 5 + 2")
print(result) # Output: 52

Constraint: eval() cannot handle statements like if, for, or assignments (x = 5). It only works for things that return a value.


exec(code) can handle complex blocks of Python code, including function definitions, loops, and classes. It always returns None.

dynamic_logic.py
logic = """
for i in range(3):
print(f"Cycle {i}")
"""
exec(logic)

3. Sandboxing: The globals and locals Args

Section titled “3. Sandboxing: The globals and locals Args”

By default, eval and exec have access to all your variables and built-in functions (including os.system, which can delete your hard drive!). To make it safer, you should pass custom dictionaries.

safe_eval.py
# Restrict access to ONLY the 'math' library and a few variables
safe_scope = {
"__builtins__": {}, # Disable all built-in functions (print, open, etc.)
"x": 10
}
# result = eval("open('passwords.txt').read()", safe_scope) # Raises NameError

When you call exec("print(1)"), Python has to:

  1. Parse the string into an AST.
  2. Compile the AST into Bytecode.
  3. Run the Bytecode.

If you are running the same string multiple times (e.g., in a loop), this is very slow. You can pre-compile the string using compile().

optimized_exec.py
source = "x += 1"
# Compile into a 'code object'
byte_code = compile(source, filename="<string>", mode="exec")
context = {"x": 0}
for _ in range(1000):
exec(byte_code, context)
print(context["x"]) # 1000

Even with sandboxing, a clever attacker can often break out of the scope using introspection (e.g., accessing ().__class__.__base__). If you need to evaluate mathematical expressions from users, use a dedicated library like simpleeval or a formal parser.


ToolInputOutputBest Use Case
eval()Expression string.The result value.Simple math/logic parsers.
exec()Block of code.None.Dynamic plugins or class creation.
compile()String code.Code object.Performance optimization for loops.
ast.literal_eval()Constant string.Python literal.The safe way to parse strings into dicts/lists.