ReviseAlgo Logo

Built-in Functions

eval and exec

Dynamic code execution with security considerations

Interview: Advanced topic — security implications and ast.literal_eval are commonly discussed

Last Updated: June 12, 2026 8 min read

eval() and exec() allow executing Python code from strings. eval() evaluates a single expression and returns its value, while exec() executes statements (assignments, function definitions, imports) and returns None. Both are powerful but extremely dangerous with untrusted input.

eval(expression)

  • Expression only: Evaluates a single Python expression — no statements (if, for, def, import)
  • Returns value: The result of the expression evaluation
  • Globals/locals: eval(expr, globals_dict, locals_dict) — controls what names are available
  • Security risk: NEVER use eval() with user input — it can execute arbitrary code including os.system()

exec(code)

  • Full statements: Can execute any Python code — assignments, function defs, imports, loops
  • Returns None: Modifies the namespace in-place instead of returning a value
  • Globals/locals: Same as eval — pass dicts to control the execution namespace
  • Even more dangerous: Can define functions, import modules, access files — full Python power

CRITICAL SECURITY WARNING

NEVER use eval() or exec() with user-supplied strings. eval("__import__('os').system('rm -rf /')") would delete files. Even restricting __builtins__ is insufficient — Python's object model allows escaping sandboxes. Use ast.literal_eval() for safe literal evaluation.

Safe Alternatives

  • ast.literal_eval(): Safely evaluates strings containing Python literals (numbers, strings, lists, dicts, booleans, None)
  • json.loads(): For JSON data — much faster and safer than eval()
  • operator module: For dynamic operations — operator.add(a, b) instead of eval("a + b")
  • Dict lookup: For dispatching — use a dict of functions instead of eval()-based dispatch

compile() + eval/exec

For repeated evaluation, compile the code string first: code = compile(expr, '', 'eval'). Then pass the compiled code to eval()/exec(). This separates compilation from execution and allows caching the compiled object.

Use Cases

Dynamic formula evaluation in calculators and spreadsheets

Code generation tools and DSLs (domain-specific languages)

Interactive Python shells and REPL implementations

Plugin systems that need to load Python code dynamically

Configuration file parsing (with safe alternatives like ast.literal_eval)

Common Mistakes

Using eval() with user input — CRITICAL security vulnerability allowing arbitrary code execution

Thinking __builtins__ restriction makes eval safe — it doesn't, Python's object model allows escaping

Using eval() when ast.literal_eval() suffices — literal_eval is safe for literals (lists, dicts, numbers)

Using exec() when a dict dispatch or template would be simpler and safer

Forgetting that exec() returns None — it modifies the namespace, not returns a value