exec() in Python 2026: Dynamic Statement Execution + Security Risks & Safe Alternatives
The built-in exec() function dynamically executes Python statements (code blocks) from a string or code object. In 2026 it remains a powerful metaprogramming tool for dynamic script loading, configuration-driven execution, REPLs, code generation, and plugin systems — but like eval(), it is extremely dangerous when used with untrusted input due to arbitrary code execution risks.
With Python 3.12–3.14+ offering improved AST support, better restricted execution options, and heightened security awareness (restrictedpython, sandboxing, subprocess isolation), exec() is used far more restrictively. This March 23, 2026 update explains how exec() works today, real-world (trusted) use cases, severe security warnings, performance notes, and modern safe alternatives.
TL;DR — Key Takeaways 2026
exec(source, globals=None, locals=None)→ executes string/code object as Python statements- 2026 security rule: NEVER use exec() on untrusted input — full code injection risk
- Safe alternative: ast.literal_eval() for literals, restrictedpython for restricted code, subprocess for isolation
- Main safe use cases: trusted config scripts, metaprogramming, REPLs, code generation (trusted sources only)
- Performance: Compile once with compile(), exec() many times for speed
1. Basic Usage — Executing Statements
# Simple statement execution
code = "x = 10\nprint(x * 2)"
exec(code)
# Output: 20
# With custom namespace (safer)
namespace = {}
exec("def greet(): print('Hello 2026')", namespace)
namespace["greet"]() # Hello 2026
2. Real-World Patterns in 2026 (Trusted Sources Only!)
Trusted Configuration Script Execution
def load_script_config(script: str) -> dict:
# WARNING: Only use on trusted scripts!
safe_globals = {"__builtins__": {}, "print": print}
local = {}
exec(script, safe_globals, local)
return local
# Trusted example (from your own file)
script = "result = 42\nname = 'Alice'"
config = load_script_config(script)
print(config) # {'result': 42, 'name': 'Alice'}
Dynamic Class / Function Generation
def create_class(class_name: str, base_class):
code = f"class {class_name}({base_class.__name__}):\n def run(self): print('Dynamic!')"
namespace = {}
exec(code, {"__builtins__": {}, base_class.__name__: base_class}, namespace)
return namespace[class_name]
Dynamic = create_class("Dynamic", object)
Dynamic().run() # Dynamic!
3. Security Risks & Modern Alternatives in 2026
| Approach | Security Level | Use Case | Recommendation 2026 |
|---|---|---|---|
| exec(code) | Very low (arbitrary code exec) | Trusted code only | Avoid with user input |
| ast.literal_eval() | High (safe literals only) | Simple data structures | Preferred for config parsing |
| restrictedpython | Medium–High | Restricted dynamic code | Use for semi-trusted plugins |
| subprocess / separate process | Very high | Untrusted code | Safest for unknown sources |
4. Best Practices & Performance in 2026
- Never exec untrusted input — use ast.literal_eval() or restrictedpython
- Restrict namespace — always pass {"__builtins__": {}} or safe globals
- Type hints 2026:
from typing import Any, Dict def safe_exec(code_str: str, safe_globals: Dict[str, Any]) -> Dict[str, Any]: local: Dict[str, Any] = {} exec(compile(code_str, "", "exec"), {"__builtins__": {}} | safe_globals, local) return local - Performance: compile() once, exec() multiple times — significant speedup for repeated code
- Free-threading (3.14+): Code objects immutable — safe to share; use locks for namespace modification
Conclusion — exec() in 2026: Powerful but Highly Restricted
exec() enables full dynamic statement execution — useful for trusted metaprogramming, configuration scripts, and REPLs — but it is one of Python’s highest security risks when misused. In 2026, restrict it to trusted sources, prefer ast.literal_eval() for literals, restrictedpython for semi-trusted code, and subprocess for isolation. When used correctly, it’s a clean way to run dynamic logic at runtime.
Next steps:
- Audit your codebase for exec() — replace untrusted uses immediately
- Related articles: compile() in Python 2026 • eval() in Python 2026