Python exec(): Execute dynamic code — syntax, globals and locals, statements vs expressions, compile() modes, security risks, sandboxing, pitfalls, and practical examples > dev

Skip to content

Entire search within the site

👈Go back dev

Python Python exec(): Execute dynamic code — syntax, globals and locals, stat…

page info

name Goposu datetime⏰ 25-10-11 17:44 hit👁️ 20 comment💬 0

text

Python exec(): Execute dynamic code — syntax, globals and locals, statements vs expressions, compile() modes, security risks, sandboxing, pitfalls, and practical examples

Python exec(): Run dynamically generated Python code

exec() executes Python statements from a string or compiled code object. Unlike eval(), which evaluates an expression and returns a value, exec() can run blocks of code including assignments, function/class definitions, loops, and imports. This flexibility is powerful but risky if inputs aren’t trusted; use strict scoping and whitelisting.

Syntax

exec(source, globals=None, locals=None)
  • source: A string of Python code or a compiled code object.
  • globals: Optional dictionary for the global namespace used during execution.
  • locals: Optional dictionary for the local namespace used during execution.

Quick examples

# Define variables and functionscode = """x = 2y = 3def add(a, b):return a + bz = add(x, y)"""ns = {}exec(code, ns)print(ns["z"])           # 5print(ns["add"](10, 20)) # 30

Globals and locals

exec() resolves names via globals and locals. If omitted, the current scope (including built-ins) is used. To control effects and limit access, pass explicit dicts and consider removing built-ins.

# Restrict the environmentsafe_globals = {"__builtins__": {}}   # remove built-inssafe_locals = {}exec("a = 10\nb = 20\nc = a + b", safe_globals, safe_locals)print(safe_locals["c"])  # 30

Statements vs expressions

  • exec(): Runs statements (assignments, defs, loops, imports). Returns None.
  • eval(): Evaluates a single expression and returns its value.
# exec can define functions and classesexec("""class Greeter:def hello(self):return 'hi'""")print(Greeter().hello())  # hi

compile() modes and precompilation

Use compile() to pre-parse code, validate its type, and reuse efficiently. Modes: "exec" for statements, "eval" for expressions, "single" for a single interactive statement.

# Pre-compile a statement blocksrc = "total = sum(range(5))"code_obj = compile(src, filename="", mode="exec")
scope = {"builtins": {}} exec(code_obj, scope) print(scope["total"])  # 10
Compile a single interactive statement
stmt = compile("print('hello')", "", "single") exec(stmt)

Security risks and sandboxing

  • Arbitrary code execution: Untrusted input can import modules, read/write files, or execute system calls.
  • Built-ins exposure: Without restrictions, dangerous functions (e.g., __import__) are available.
  • Mitigation: Remove built-ins, whitelist allowed functions/modules, and validate code (regex/AST). Consider running in isolated processes.
# Whitelist-only environmentimport mathenv = {"__builtins__": {},        # remove all built-ins"math": math,              # allow math only}user_code = "result = math.sqrt(49)"exec(user_code, env)print(env["result"])  # 7.0

Common patterns

  • Dynamic function creation: Generate small utilities or formulas at runtime.
  • Configuration-driven scripts: Execute trusted admin-authored blocks with a limited namespace.
  • Educational/repl tools: Run code snippets with timeouts and sandboxing.
# Build a function from a templatetmpl = """def f(x, y):return x {op} y"""ns = {}exec(tmpl.format(op="*"), ns)print(ns["f"](6, 7))  # 42

Pitfalls and how to avoid them

  • Silent failures: exec() returns None; inspect namespaces for results.
  • State leaks: Running in the current scope can mutate globals; prefer isolated dicts.
  • Debuggability: Generated code obscures stack traces; set meaningful filename in compile().
  • Performance: Repeatedly parsing strings is expensive; pre-compile for reuse.

Practical examples

# 1) Execute a trusted setup scriptsetup = '''threshold = 0.8def score(x):return x * 100'''conf = {"__builtins__": {}}exec(setup, conf)print(conf["threshold"], conf["score"](0.9))  # 0.8 90.0
2) Evaluate per-request formulas with compile()
formula = compile("out = base * (1 + rate)", "", "exec") ns = {"builtins": {}, "base": 100, "rate": 0.25} exec(formula, ns) print(ns["out"])  # 125.0
3) Capture output safely (provide print)
def safe_print(*args, **kwargs): pass  # no-op or custom logger env = {"builtins": {}, "print": safe_print} exec("print('This will be logged')", env)

FAQ

Can exec() return a value?
No. It executes statements and returns None. Store results in the provided namespace dict and read them after.
How do I limit what exec() can access?
Provide custom globals/locals, set __builtins__ to an empty dict, and expose only whitelisted functions/modules.
Should I use exec() for user input?
Generally no. Use parsers, domain-specific languages, or vetted whitelists; consider isolated processes for untrusted code.

Related keywords

Python exec, dynamic code execution, globals locals, sandbox, compile modes, security, whitelist, code generation, statements vs expressions

👍good0 👎nogood 0

comment list 0

There are no registered comments.

이미지 목록

전체 19건 1 페이지
게시물 검색
Copyright © https://goposu.com All rights reserved.
View PC version