1

How to evaluate user input mathematical expressions such as power safely? Tried using ast.literal_eval but it raises an exception.

>>> import ast
>>> ast.literal_eval('2**2')
ValueError: malformed node or string: <_ast.BinOp object at ...>
Sawel
  • 929
  • 7
  • 17
  • Hint: `2**2` is not a literal. – Jörg W Mittag Jun 17 '19 at 08:23
  • `2+3` is not a literal as well, and yet it works. – Sawel Jun 17 '19 at 08:51
  • According to the documentation, it shouldn't work, so I would consider that leaking a private internal implementation detail, and would not rely on it. I wouldn't bet, for example, that it works the same way in IronPython, Jython, PyPy, Typhon, Pynie, PythonOMR, TrufflePython, etc. – Jörg W Mittag Jun 17 '19 at 10:08
  • See my answer to a similar question: https://stackoverflow.com/questions/15197673/using-pythons-eval-vs-ast-literal-eval/68732605#68732605 – Jay M Aug 10 '21 at 19:38

2 Answers2

1

ast.literal_eval (although it actually supports addition and substraction) is intended for evaluating literals only. To safely evaluate mathematical expressions, you should construct the AST yourself using ast.parse(some_expression, mode="eval") and check if it only contains literals and mathematical operations using ast.walk(). To evaluate an AST use something like eval(compile(the_ast, "<string>", "eval")).

See this website for more information about ASTs: https://greentreesnakes.readthedocs.io/

Maximouse
  • 4,170
  • 1
  • 14
  • 28
1

You can use seval package for arithmetic operations and literals safe evaluation.

>>> import seval
>>> seval.safe_import('2 ** 2')
4
Sawel
  • 929
  • 7
  • 17