pythonstringpython-3.xequation

Safely evaluate simple string equation


I'm writing a program in which an equation is inputted as a string, then evaluated. So far, I've come up with this:

test_24_string = str(input("Enter your answer: "))
test_24 = eval(test_24_string)

I need both a string version of this equation and an evaluated version. However, eval is a very dangerous function. Using int() doesn't work, though, because it's an equation. Is there a Python function that will evaluate a mathematical expression from a string, as if inputting a number?


Solution

  • One way would be to use . It's mostly a module for optimizing (and multithreading) operations but it can also handle mathematical python expressions:

    >>> import numexpr
    >>> numexpr.evaluate('2 + 4.1 * 3')
    array(14.299999999999999)
    

    You can call .item on the result to get a python-like type:

    >>> numexpr.evaluate('17 / 3').item()
    5.666666666666667
    

    It's a 3rd party extension module so it may be total overkill here but it's definetly safer than eval and supports quite a number of functions (including numpy and math operations). If also supports "variable substitution":

    >>> b = 10
    >>> numexpr.evaluate('exp(17) / b').item()
    2415495.27535753
    

    One way with the python standard library, although very limited is ast.literal_eval. It works for the most basic data types and literals in Python:

    >>> import ast
    >>> ast.literal_eval('1+2')
    3
    

    But fails with more complicated expressions like:

    >>> ast.literal_eval('import os')
    SyntaxError: invalid syntax
    
    >>> ast.literal_eval('exec(1+2)')
    ValueError: malformed node or string: <_ast.Call object at 0x0000023BDEADB400>
    

    Unfortunatly any operator besides + and - isn't possible:

    >>> ast.literal_eval('1.2 * 2.3')
    ValueError: malformed node or string: <_ast.BinOp object at 0x0000023BDEF24B70>
    

    I copied part of the documentation here that contains the supported types:

    Safely evaluate an expression node or a string containing a Python literal or container display. The string or node provided may only consist of the following Python literal structures: strings, bytes, numbers, tuples, lists, dicts, sets, booleans, and None.