If you have a string that contains Python literals, such as strings, floats etc, you can use ast.literal_eval
to evaluate its value instead of eval
. This has the added feature of allowing only certain syntax.
>>> import ast
>>> code = """(1, 2, {'foo': 'bar'})"""
>>> object = ast.literal_eval(code)
>>> object
(1, 2, {'foo': 'bar'})
>>> type(object)
<class 'tuple'>
However, this is not secure for execution of code provided by untrusted user, and it is trivial to crash an interpreter with carefully crafted input
>>> import ast
>>> ast.literal_eval('()' * 1000000)
[5] 21358 segmentation fault (core dumped) python3
Here, the input is a string of ()
repeated one million times, which causes a crash in CPython parser. CPython developers do not consider bugs in parser as security issues.