1

I was searching for a safe way to eval simple arithmetic expressions. I'm aware of the difficulties of making eval() "more safe", but then I learned about ast.literal_eval()

I tried it, with the following example:

>>> ast.literal_eval("1+1")
2

Nice! Now try 1 times 1...

>>> ast.literal_eval("1*1")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/jldiaz/miniconda3/lib/python3.6/ast.py", line 85, in literal_eval
    return _convert(node_or_string)
  File "/home/jldiaz/miniconda3/lib/python3.6/ast.py", line 84, in _convert
    raise ValueError('malformed node or string: ' + repr(node))
ValueError: malformed node or string: <_ast.BinOp object at 0x7fac8830aa58>

What does this mean? Malformed string? However it can be parsed without errors:

>>> result = ast.parse("1*1")
>>> ast.dump(result)
'Module(body=[Expr(value=BinOp(left=Num(n=1), op=Mult(), right=Num(n=1)))])'

The AST looks ok, and the operation to perform is Mult(). However it fails. Apparently it is the operation which is failing, because the AST for the first succesful experiment was identical, only with op=Add().

I tried other operations. Division (/), integer division (//) and modulo (%) all fail. Only addition (+) and substraction (-) seem to work.

Am I missing something? Surprisingly I was unable to find any information about this problem or the operations supported by ast.literal_eval()

JLDiaz
  • 1,248
  • 9
  • 21
  • 1
    You'll need to build a proper parser for a calculater, `liter_eval` works for addition and subtraction but only because of complex numbers https://stackoverflow.com/questions/40584417/why-does-ast-literal-eval5-7/ – Chris_Rands Feb 23 '18 at 12:50
  • 1
    A second relevant dupe target: jfs has a very nice solution, https://stackoverflow.com/questions/2371436/evaluating-a-mathematical-expression-in-a-string – Chris_Rands Feb 23 '18 at 12:52

0 Answers0