Built-in Functions
eval and exec
Dynamic code execution with security considerations
Interview: Advanced topic — security implications and ast.literal_eval are commonly discussed
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