vars() in Python 2026: Accessing Object Namespace + Modern Introspection Patterns str() in Python 2026: String Conversion + Modern Formatting & Best Practices type() in Python 2026: Dynamic Type Inspection & Object Creation + Modern Patterns super() in Python 2026: Method Resolution & Modern Inheritance Patterns tuple() in Python 2026: Immutable Sequences + Modern Patterns & Best Practices staticmethod() in Python 2026: Static Methods, Utility Functions & Modern Best Practices sum() in Python 2026: Summing Iterables + Modern Numeric Patterns & Best Practices sorted() in Python 2026: Sorting Iterables + Modern Patterns & Best Practices slice() in Python 2026: Creating Slice Objects + Modern Patterns & Best Practices setattr() in Python 2026: Dynamic Attribute Setting + Modern Patterns & Safety set() in Python 2026: Mutable Sets Creation + Modern Patterns & Best Practices round() in Python 2026: Rounding Numbers + Modern Precision & Use Cases reversed() in Python 2026: Reverse Iteration + Modern Patterns & Best Practices repr() in Python 2026: Official String Representation + Modern Debugging & Serialization Use Cases pow() in Python 2026: Power & Modular Exponentiation + Modern Use Cases & Best Practices property() in Python 2026: Properties, Getters/Setters & Modern Patterns ord() in Python 2026: Unicode Code Point from Character + Modern Use Cases & Best Practices open() in Python 2026: File Handling + Modern I/O Patterns & Best Practices range() in Python 2026: Efficient Sequence Generation + Modern Patterns & Best Practices print() in Python 2026: Output Formatting + Modern CLI & Debugging Patterns View all in this category →

eval() in Python 2026: Dynamic Expression Evaluation + Security Risks & Safe Alternatives

Built In Function Mar 07, 2023

eval() in Python 2026: Dynamic Expression Evaluation + Security Risks & Safe Alternatives

The built-in eval() function evaluates a string as a Python expression and returns the result. In 2026 it remains one of the most powerful — and most dangerous — built-ins, used for dynamic calculation, configuration parsing, interactive shells, and some metaprogramming scenarios. However, its ability to execute arbitrary code makes it a top security risk when handling untrusted input.

With Python 3.12–3.14+ offering better AST parsing, improved restricted execution tools, and growing security best practices (restrictedpython, ast.literal_eval, sandboxing), eval() is used far more cautiously. This March 23, 2026 update explains how eval() works today, real-world (trusted) use cases, severe security warnings, performance notes, and modern safe alternatives.

TL;DR — Key Takeaways 2026

  • eval(expression, globals=None, locals=None) → executes string as Python expression
  • 2026 security rule: NEVER use eval() on untrusted input — remote code execution risk
  • Safe alternative: ast.literal_eval() for simple literals (int, str, list, dict…)
  • Main safe use cases: trusted config expressions, interactive REPLs, calculator apps
  • Performance: Fast for small expressions — cache compiled code objects if reused

1. Basic Usage — Evaluating Expressions


x = 10
print(eval("x * 2 + 5"))         # 25

# With custom globals/locals (safer)
safe_globals = {"__builtins__": {}, "x": x}
print(eval("x * 3", safe_globals))  # 30

2. Real-World Patterns in 2026 (Trusted Input Only!)

Trusted Config Expression Evaluation


import math

def load_expression(expr: str) -> float:
    # WARNING: Only use on trusted config!
    safe_globals = {"__builtins__": {}, "pi": math.pi, "sin": math.sin}
    return eval(expr, safe_globals)

# Trusted example (from your own config)
result = load_expression("sin(pi/2) + 1")
print(result)  # 2.0

Simple Calculator / Interactive Shell


def simple_calculator():
    while True:
        expr = input("Enter expression (or q to quit): ")
        if expr.lower() == "q":
            break
        try:
            print(eval(expr))
        except Exception as e:
            print(f"Error: {e}")

3. Security Risks & Modern Alternatives in 2026

Approach Security Level Use Case Recommendation 2026
eval(expr)Very low (arbitrary code exec)Never with user inputAvoid completely in untrusted contexts
ast.literal_eval(expr)High (safe literals only)Config, simple data structuresPreferred for safe parsing
restrictedpython / safe_evalMedium–HighRestricted dynamic expressionsUse for semi-trusted plugins
subprocess / separate processVery highUntrusted codeSafest for unknown sources

4. Best Practices & Performance in 2026

  • Never eval untrusted input — use ast.literal_eval() for safe literals
  • Restrict globals — always pass {"__builtins__": {}} or safe namespace
  • Type hints 2026:
    
    from typing import Any
    
    def safe_eval(expr: str, safe_globals: dict[str, Any]) -> Any:
        return eval(expr, {"__builtins__": {}} | safe_globals, {})
    
  • Performance: compile once with compile(), then eval() multiple times
  • Free-threading (3.14+): Safe when globals/locals are not modified concurrently

Worked Example: Safer Alternatives to eval()

Removing __builtins__ does not make eval() safe; attribute tricks can still reach dangerous objects, and even a harmless-looking expression such as 9**9**9 can freeze a process. Never pass untrusted input to eval(). For data, use ast.literal_eval() or json.loads(). For simple formulas, parse the expression with ast and allow only the node types you expect.

import ast
import operator as op

print(ast.literal_eval("[1, 2.5, {'a': True}]"))     # data only

OPS = {ast.Add: op.add, ast.Sub: op.sub, ast.Mult: op.mul,
       ast.Div: op.truediv, ast.USub: op.neg}

def calc(expr: str, variables: dict[str, float]) -> float:
    def walk(node):
        if isinstance(node, ast.Constant) and isinstance(node.value, (int, float)):
            return node.value
        if isinstance(node, ast.Name) and node.id in variables:
            return variables[node.id]
        if isinstance(node, ast.BinOp) and type(node.op) in OPS:
            return OPS[type(node.op)](walk(node.left), walk(node.right))
        if isinstance(node, ast.UnaryOp) and type(node.op) in OPS:
            return OPS[type(node.op)](walk(node.operand))
        raise ValueError(f"not allowed: {ast.dump(node)[:40]}")
    return walk(ast.parse(expr, mode="eval").body)

print(calc("price * qty - discount", {"price": 9.5, "qty": 4, "discount": 3}))   # 35.0
for bad in ["__import__('os')", "2 ** 100"]:
    try:
        calc(bad, {})
    except ValueError as exc:
        print("rejected:", bad)

Common Mistakes

  • Calling eval(input()): any user can run arbitrary code
  • Trusting an empty __builtins__ as a sandbox
  • Using eval() to parse numbers or lists: use float(), int() or literal_eval()

Quick Summary

  • eval() evaluates one expression with full Python power
  • Only use it on code you wrote yourself
  • Prefer literal_eval, json or a whitelisted ast evaluator

Conclusion — eval() in 2026: Powerful but Highly Restricted

eval() allows dynamic expression evaluation — useful for trusted calculators, configs, and metaprogramming — but it is one of Python’s biggest security risks when misused. In 2026, restrict it to trusted sources, prefer ast.literal_eval() for safe cases, and use restricted environments or subprocess for anything untrusted. When used correctly, it’s a clean way to run dynamic math expressions at runtime.

Next steps:

  • Audit your codebase for eval() — replace untrusted uses immediately

Related Tutorials

Share:
Last updated: March 2023
Built-in Functions in Python 2026 str() in Python 2026: String Conversion + Modern Formatting & Best Practices memoryview with JAX in Python 2026: Zero-Copy NumPy → JAX Array Interop + Efficient ML Examples memoryview with TensorFlow in Python 2026: Zero-Copy NumPy → Tensor Interop + GPU Pinning & ML Examples memoryview with TensorFlow in Python 2026: Zero-Copy NumPy → Tensor Interop + ML Examples memoryview with NumPy & PyTorch in Python 2026: Zero-Copy Views, Efficient Slicing & ML Interop Examples memoryview with NumPy in Python 2026: Zero-Copy Views, Efficient Slicing & Real ML Examples memoryview() in Python 2026: Zero-Copy Magic for Large Binary Data + Real Examples import() in Python 2026: How It Works, Security Risks & Modern Alternatives (importlib) zip() in Python 2026: How to Use It, strict=True Behavior & Real-World Examples vars() in Python 2026: Accessing Object Namespace + Modern Introspection Patterns type() in Python 2026: Dynamic Type Inspection & Object Creation + Modern Patterns tuple() in Python 2026: Immutable Sequences + Modern Patterns & Best Practices super() in Python 2026: Method Resolution & Modern Inheritance Patterns sum() in Python 2026: Summing Iterables + Modern Numeric Patterns & Best Practices staticmethod() in Python 2026: Static Methods, Utility Functions & Modern Best Practices sorted() in Python 2026: Sorting Iterables + Modern Patterns & Best Practices slice() in Python 2026: Creating Slice Objects + Modern Patterns & Best Practices setattr() in Python 2026: Dynamic Attribute Setting + Modern Patterns & Safety set() in Python 2026: Mutable Sets Creation + Modern Patterns & Best Practices