Use literal_eval instead of eval

  • code
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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)

  • test
1
2
3
4
5
6
safe_eval('1 + 2 / 3')
Out[3]: 1.6666666666666665
safe_eval('(1 + 2) / 3')
Out[4]: 1.0
safe_eval('-1')
Out[5]: -1
# NOTE: I am not responsible for any expired content.
create@2021-10-25T01:49:59+08:00
update@2021-11-09T07:21:25+08:00
comment@https://github.com/ferstar/blog/issues/44
加载评论