(Sponsors) Get started learning Python with DataCamp's free Intro to Python tutorial. Learn Data Science by completing interactive coding challenges and watching videos by expert instructors. Start Now!
Python eval() function
Updated on Jan 07, 2020
The eval()
allows us to execute arbitrary strings as Python code. It accepts a source string and returns an object.
Its syntax is as follows:
Syntax:
eval(expr, globals=None, locals=None)
PARAMETER | DESCRIPTION |
---|---|
expr (required) |
expr can be any valid Python expression |
globals (optional) |
Global namespace to use while executing the source. It must be a dictionary. If not provided then the current global namespace will be used. |
locals (optional) |
Local namespace to use while executing the source. It can be any mapping. If omitted, it defaults to globals dictionary. |
If both globals
and locals
are omitted, the current global and local namespaces are used.
Here is an example demonstrating how eval()
works:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | >>>
>>> eval("5 == 5")
True
>>>
>>>
>>> eval("4 < 10")
True
>>>
>>>
>>> eval("8 + 4 - 2 * 3")
6
>>>
>>>
>>> eval("'py ' * 5")
'py py py py py '
>>>
>>>
>>> eval("10 ** 2")
100
>>>
>>>
>>> eval("'hello' + 'py'")
'hellopy'
>>>
|
Try it out:
The eval()
is not just limited to simple expression. We can execute functions, call methods, reference variables and so on.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | >>>
>>> eval("abs(-11)")
11
>>>
>>>
>>> eval('"hello".upper()')
'HELLO'
>>>
>>>
>>> import os
>>>
>>>
>>> eval('os.getcwd()') # get current working directory
'/home/thepythonguru'
>>>
>>>
>>> x = 2
>>>
>>> eval("x+4") # x is referenced inside the expression
6
>>>
|
Try it out:
Note that the eval()
works only with an expression. Trying to pass a statement causes a SyntaxError
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | >>>
>>> eval('a=1') # assignment statement
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1
a=1
^
SyntaxError: invalid syntax
>>>
>>>
>>> eval('import re') # import statement
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1
import re
^
SyntaxError: invalid syntax
>>>
|
Evil eval() #
You should never pass untrusted source to the eval()
directly. As it is quite easy for the malicious user to wreak havoc on your system. For example, the following code can be used to delete all the files from the system.
1 2 3 | >>>
eval('os.system("RM -RF /")') # command is deliberately capitalized
>>>
|
The above code would fail if the os module is not available in your current global scope. But we can easily circumvent this by using the __import__()
built-in function.
1 2 3 | >>>
>>> eval("__import__('os').system('RM -RF /')") # command is deliberately capitalized
>>>
|
So is there any way to make eval()
safe?
Specifying Namespaces #
The eval()
optionally accepts two mappings that serve as a global and local namespaces for the expression to be executed. If mapping(s) are not provided then the current values of global and local namespaces will be used.
Here are some examples:
Example 1:
1 2 3 4 5 6 7 8 9 10 11 12 13 | >>>
>>> globals = {
... 'a': 10,
... 'fruits': ['mangoes', 'peaches', 'bananas'],
... }
>>>
>>>
>>> locals = {}
>>>
>>>
>>> eval("str(a) + ' ' + fruits[0]", globals, locals)
'10 mangoes'
>>>
|
Example 2:
1 2 3 4 | >>>
>>> eval('abs(-100)', {}, {})
100
>>>
|
Even though we have passed empty dictionaries as global and local namespaces, eval()
still has access to built-ins (i.e __builtins__
).
1 2 3 4 5 6 7 8 | >>>
>>> dir(__builtins__)
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError',
...
...
'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted'
, 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']
>>>
|
To remove built-ins from the global namespace pass a dictionary containing a key __builtins__
with the value None
.
Example 3:
1 2 3 4 5 6 7 | >>>
>>> eval('abs(-100)', {'__builtins__':None}, {})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
TypeError: 'NoneType' object is not subscriptable
>>>
|
Even after removing the access to built-ins functions, eval()
is still not safe. Consider the following listing.
1 2 3 | >>>
>>> eval("5**98765432111123", {'__builtins__':None}, {})
>>>
|
This deceptively simple looking expression is enough to tank your CPU.
The key takeaway is that only use eval()
with the trusted source.
Other Tutorials (Sponsors)
This site generously supported by DataCamp. DataCamp offers online interactive Python Tutorials for Data Science. Join over a million other learners and get started learning Python for data science today!
View Comments