Complete guide to Python's eval function covering syntax, security considerations, and practical examples of expression evaluation.
Last modified April 11, 2025
This comprehensive guide explores Python’s eval function, which evaluates expressions dynamically. We’ll cover syntax, security risks, practical applications, and best practices for safe evaluation.
The eval function parses and evaluates a string as a Python expression. It returns the result of the evaluated expression. The function can optionally take globals and locals dictionaries for variable scope.
Key characteristics: evaluates strings as code, supports expression-only evaluation (not statements), and can be dangerous with untrusted input. Always validate input before using eval in production code.
Here’s simple usage showing how eval can evaluate mathematical expressions and basic Python operations from strings.
basic_eval.py
result = eval(“2 + 3 * 4”) print(result) # 14
x = 10 y = 5 print(eval(“x + y”)) # 15
print(eval(“10 > 5 and 3 < 4”)) # True
This example shows eval evaluating different expression types. It can handle arithmetic, variable references, and boolean logic when the variables are in scope.
The function returns the result of the evaluated expression, allowing dynamic code execution based on string input. Note that only expressions work, not statements like assignments or loops.
eval can take optional globals and locals dictionaries to control variable access. This example demonstrates restricted evaluation.
scope_eval.py
safe_dict = {‘x’: 5, ‘y’: 10} result = eval(“x + y”, safe_dict) print(result) # 15
try: eval(“z + 5”, safe_dict) except NameError as e: print(f"Error: {e}") # name ‘z’ is not defined
try: eval(“len(’test’)”, {’builtins’: None}) except NameError as e: print(f"Error: {e}") # name ’len’ is not defined
This shows how to control variable access in eval. The first example uses a custom dictionary for variables. The others demonstrate restricted access to undefined variables and built-ins.
Restricting globals and locals is crucial for security when evaluating untrusted input. Always limit available namespaces when possible.
This practical example creates a safe calculator that evaluates mathematical expressions while preventing dangerous operations.
calculator.py
import math
def safe_eval(expr): allowed_names = { k: v for k, v in math.dict.items() if not k.startswith(’_’) } allowed_names.update({‘abs’: abs, ‘round’: round})
try:
return eval(expr, {'__builtins__': None}, allowed_names)
except (SyntaxError, NameError, TypeError) as e:
return f"Error: {e}"
print(safe_eval(“sqrt(16) + log10(100)”)) # 6.0 print(safe_eval("import(‘os’).system(’ls’)")) # Error: name ‘import’ is not defined
This calculator allows only specific math functions while blocking dangerous operations. It demonstrates how to create a safe evaluation environment.
The function whitelists math operations and catches potential errors. The second example shows how it prevents malicious code execution attempts.
eval can be used for simple template evaluation where expressions need to be dynamically inserted into strings.
template_eval.py
def eval_template(template, context): try: return eval(f’f"""{template}"""’, {’builtins’: None}, context) except Exception as e: return f"Template error: {e}"
user = {’name’: ‘Alice’, ‘age’: 30} template = “Hello {name}, you are {age} years old. Next year: {age+1}” print(eval_template(template, user))
This example shows how to use eval with f-strings for dynamic template evaluation. The context dictionary provides the variables.
While powerful, this approach should only be used with trusted templates. Consider alternatives like string.Template for untrusted input.
This advanced example demonstrates evaluating JSON configurations that contain simple expressions, useful for dynamic settings.
config_eval.py
import json import math
def eval_config(config_str): config = json.loads(config_str) context = { ‘math’: math, ’env’: {‘width’: 1024, ‘height’: 768} }
if 'formula' in config:
try:
config['value'] = eval(
config['formula'],
{'__builtins__': None},
context
)
except Exception as e:
config['error'] = str(e)
return config
config_json = ‘’’{ “name”: “display”, “formula”: “math.sqrt(env[‘width’]**2 + env[‘height’]**2)” }’’’
result = eval_config(config_json) print(result[‘value’]) # 1280.0 (diagonal of 1024x768 display)
This shows how to safely evaluate expressions in JSON configurations. The formula calculates the diagonal length using the Pythagorean theorem.
The example maintains security by restricting built-ins while allowing specific math operations and environment variables through a context dict.
Avoid untrusted input: Never eval raw user input directly
Restrict namespaces: Always provide limited globals/locals
Use alternatives: Consider ast.literal_eval for simple needs
Validate input: Sanitize expressions before evaluation
Document risks: Clearly warn about security implications
My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.
List all Python tutorials.