import ast
import operator
valid_ops = {
ast.Add: operator.add,
ast.Sub: operator.sub,
ast.Mult: operator.mul,
ast.Div: operator.truediv,
ast.USub: operator.neg, # negative number
}
def safe_eval(expr):
"""Use `ast.literal_eval` instead of `eval`
via: https://stackoverflow.com/a/20748308
"""
def _eval(node):
if isinstance(node, ast.Expression):
return _eval(node.body)
if isinstance(node, ast.Str):
return node.s
if isinstance(node, ast.Num):
return node.n
if isinstance(node, ast.UnaryOp):
return valid_ops[type(node.op)](node.operand.n)
if isinstance(node, ast.BinOp):
return valid_ops[type(node.op)](_eval(node.left), _eval(node.right))
raise TypeError('Unsupported type {}'.format(node))
return _eval(ast.parse(expr, mode='eval').body)