Safe way to parse user-supplied mathematical formula in Python

Viewed 7709

Is there a math expressions parser + evaluator for Python?

I am not the first to ask this question, but answers usually point to eval(). For instance, one could do this:

>>> safe_list = ['math','acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'cosh', 'degrees', 'e', 'exp', 'fabs', 'floor', 'fmod', 'frexp', 'hypot', 'ldexp', 'log', 'log10', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'abs']
>>> safe_dict = dict([ (k, locals().get(k, None)) for k in safe_list ])
>>> s = "2+3"
>>> eval(s, {"__builtins__":None}, safe_dict)
5

But this is not safe:

>>> s_badbaduser = """
... (lambda fc=(
...     lambda n: [
...         c for c in 
...             ().__class__.__bases__[0].__subclasses__() 
...             if c.__name__ == n
...         ][0]
...     ):
...     fc("function")(
...         fc("code")(
...             0,0,0,0,"KABOOM",(),(),(),"","",0,""
...         ),{}
...     )()
... )()
... """
>>> eval(s_badbaduser, {"__builtins__":None}, safe_dict)
Segmentation fault

Also, using eval for parsing and evaluating mathematical expressions just seems wrong to me.

I have found PyMathParser, but it also uses eval under the hood and is no better:

>>> import MathParser
>>> m=MathParser.PyMathParser()
>>> m.expression = s_badbaduser
>>> m.evaluate();
Segmentation fault

Is there a library available that would parse and evaluate mathematical expression without using Python parser?

3 Answers
Related