Skip to main content

Python eval() Function

The eval() method parses the expression passed to this method and runs python expression (code) within the program.

Syntax

eval(expression, globals=None, locals=None)

eval() Parameters

Python eval() function parameters:

ParameterConditionDescription
expressionRequiredA String, that will be evaluated as Python code
globalsOptionalA dictionary containing global parameters
localsOptionalA dictionary containing local parameters

eval() Return Value

Python eval() function returns the result evaluated from the expression.

Examples

Example 1: evaluating an arithmetic expression with eval() function

result = eval('1 + 2')
print(result) # Output: 3

output

3

Example 2: evaluating a complex expression involving a function call with eval() function

result = eval('sum([1,  2,  3,  4])')
print(result) # Output: 10

output

10

Example 3: evaluating a boolean expression with eval() function

result = eval('True and False')
print(result) # Output: False

output

False

Example 4: using eval() with custom global and local namespaces

def square(number):
return number * number

global_vars = {"square": square}
result = eval("square(5)", global_vars)
print(result) # Output: 25

output

25

Security issues of using eval() function and possible mitigations

Security issues of eval() function

The Python eval() function can expose you to some security risks.

Consider a situation where you are using a Unix system (macOS, Linux, etc.) and you have imported the os module. The os module provides a portable way to use operating system functionalities like reading or writing to a file.

If you allow users to input a value using eval(input()), the user may issue commands to change file or even delete all the files using the command: os.system('rm -rf *').

If you are using eval(input()) in your code, it is a good idea to check which variables and functions the user can use. You can see which variables and methods are available using dir() function.

Mitigations of using eval() function

Frequently, not all methods and variables that are available within the scope of eval() are required or even pose potential security threats. Therefore, it is often beneficial to limit the scope of these methods and variables for safety purposes.

To achieve this, you can provide the eval() function with optional globals and locals parameters, which are dictionaries that define the global and local namespaces for the evaluated expression.

warning

Restricting the use of eval() by passing globals and locals dictionaries will make your code secure particularly when you are using input provided by the user to the eval() method.

danger

Sometimes, eval() is not secure even with limited names. When an object and its methods are made accessible, almost anything can be done by an attacker. The only secure way is by validating the user input.

1. When both globals and locals parameters omitted

If both parameters are omitted (as in our earlier examples), the expression is executed in the current scope. You can check the available variables and methods using following code:

print(eval('dir()')

2. Passing globals parameter and locals parameter is omitted

When using eval() in Python, you can specify the global and local namespaces through the globals and locals parameters. If the locals parameter is not provided, it defaults to the globals dictionary, meaning that the global namespace will be used for both global and local variables within the evaluated expression.

note

You can check the current global and local dictionary in Python using globals() and locals() built-in methods respectively.

For example, you can pass empty dictionary as globals parameter:

from math import *
print(eval('dir()', {}))

# The code will raise an exception
print(eval('sqrt(25)', {}))

output

['__builtins__']
Traceback (most recent call last):
File "main.py", line 5, in <module>
print(eval('sqrt(25)', {}))
File "<string>", line 1, in <module>
NameError: name 'sqrt' is not defined
note

If you pass an empty dictionary as globals, only the __builtins__ are available to expression (first parameter of the eval()).

Even though we have imported the math module in the above program, expression can not access any functions provided by the math module.

For example, you can make certain methods available (the expression can only use the sqrt() and the pow() methods along with __builtins__):

from math import *
print(eval('dir()', {'sqrt': sqrt, 'pow': pow}))

output

['__builtins__', 'pow', 'sqrt']

It is also possible to change the name of the method available for the expression as you want:

from math import *
names = {'square_root': sqrt, 'power': pow}
print(eval('dir()', names))

# Using square_root in Expression
print(eval('square_root(9)', names))

output

['__builtins__', 'power', 'square_root']
3.0
note

In the above program, square_root() calculates the square root using sqrt(). However, trying to use sqrt() directly will raise an error.

You can restrict the use of __builtins__ in the expression as follows:

eval(expression, {'__builtins__': None})

3. Passing both globals and locals dictionary

To expose specific functions and variables for use within the eval() function, you can pass a dictionary to the locals parameter. This allows you to control which names are considered local within the evaluated expression.

For example, in the following program, expressions evaluated by eval() function can have sqrt() method and variable a only. All other methods and variables are unavailable.

from math import *

a = 144
result = eval('sqrt(a)', {'__builtins__': None}, {'a': a, 'sqrt': sqrt})
print(result) # Output: 12.0

output

12.0