Die Python-Funktion exec(code) führt einen String oder ein Code-Objekt als Python-Statements aus — anders als eval(), das nur Ausdrücke kennt. Damit lassen sich Funktionen, Klassen, Schleifen und mehr dynamisch generieren. Wie eval() ist exec() extrem mächtig — und extrem gefährlich, sobald die Eingabe nicht vertrauenswürdig ist.

Einleitung

exec() ist Pythons mächtigstes Code-Generierungs-Werkzeug. Anwendungsfälle sind:

  • Code-Generatoren: Templates, ORM-Mapper, Test-Generatoren.
  • Notebooks/REPLs: User-Eingabe als Code ausführen.
  • DSLs: Eigene Mini-Sprachen, die in Python übersetzt werden.

Dabei gilt dasselbe wie für eval(): Niemals mit ungeprüftem Input. exec(user_input) ist ein offener Türgriff für Angreifer.

exec() läuft im Default in den aufrufenden Globals und Locals — Variablen, die im exec'd Code definiert werden, landen also dort. Mit explizitem globals-Dict lässt sich der Scope abschotten.

Syntax

Python Syntax
exec(code, globals=None, locals=None)
Parameter
code

Ein String mit Python-Code oder ein per compile(..., mode="exec") vorbereitetes Code-Objekt.

globals

(Optional) Dict mit globalen Variablen. Default: aktuelle Globals.

locals

(Optional) Dict mit lokalen Variablen.

Rückgabewert

Immer None. Im Gegensatz zu eval() gibt exec() nie ein Ergebnis zurück — Effekte landen in den übergebenen globals/locals.

Beispiele

Statement ausführen

exec() kann mehrere Statements auf einmal verarbeiten — perfekt für mehrzeiligen generierten Code:

Python Beispiel
code = """
for i in range(3):
    print(f"Schleife {i}")
"""
exec(code)
Output
Schleife 0
Schleife 1
Schleife 2

Funktion dynamisch erzeugen

Mit exec() lässt sich eine Funktion zur Laufzeit aus einem String erzeugen — die Definition landet im übergebenen locals-Dict:

Python Beispiel
ns = {}
exec("def double(x): return x * 2", ns)
print(ns["double"](21))
Output
42

In abgeschottetem Namespace

Ein eigener globals-Dict isoliert den ausgeführten Code vom Rest des Programms:

Python Beispiel
sandbox = {"__builtins__": {"print": print}}
exec("print('läuft im sandbox')", sandbox)
# Versuch zu importieren schlägt fehl:
try:
    exec("import os", sandbox)
except ImportError as e:
    print("Blockiert:", e)
Output
läuft im sandbox
Blockiert: __import__ not found

Praktische Beispiele

Klasse aus Template generieren

dataclasses machen das ähnlich intern — sie bauen __init__ aus einer Klassen-Definition zur Laufzeit:

Python Beispiel
fields = ["name", "age", "city"]
params = ", ".join(fields)
body   = "\n        ".join(f"self.{f} = {f}" for f in fields)

template = f"""
class User:
    def __init__(self, {params}):
        {body}
    def __repr__(self):
        return f"User({{', '.join(f'{{k}}={{getattr(self, k)!r}}' for k in {fields!r})}})"
"""
ns = {}
exec(template, ns)
u = ns["User"]("Michael", 34, "Berlin")
print(u.name, u.age, u.city)
Output
Michael 34 Berlin

Compile + exec für mehrfaches Ausführen

Wenn derselbe Code-String mehrmals ausgeführt wird, lohnt sich compile() — der Parsing-Overhead fällt nur einmal an:

Python Beispiel
code = compile("total += value", "<input>", "exec")
ns = {"total": 0}
for value in [1, 2, 3, 4, 5]:
    ns["value"] = value
    exec(code, ns)
print(ns["total"])
Output
15

Praktische Hinweise

  • Niemals mit User-Input ohne intensive Validierung — Code-Injection ist die Folge.
  • In Funktionen ist exec() tricky — Schreib-Effekte auf lokale Variablen sind ohne explizites locals-Dict nicht zuverlässig.
  • Alternative: Ein dict-basiertes Konfig-Format, ast.literal_eval für Daten oder importlib für dynamisches Modul-Loading.
  • Template-Engines (Jinja2, Mako) sind die richtige Wahl für Text-Generierung — exec() für echten Python-Code.
  • Verwandte Funktionen: eval() (Ausdrücke), compile(), importlib.import_module(), types.FunctionType.
/ Weiter

Zurück zu Builtin Functions

Zur Übersicht