<-- Back to Current Category
Evaluate Formulas using eval()
By: Henry May, Sat Jul 24th, 2010
PyMathParser from bestcode.com is a small Python class to make it easy to evaluate mathematical expressions in your Python code. It let's you define supported functions, variables and it securely calls the eval() built in Python function to evaluate math formula given as a string at runtime. But why is it needed? Do we not already have eval() function in many languages?
Most languages such as PHP, Python come with an eval() function that can evaluate an expression given as a string at runtime. Using eval function, a developer can leave the job of parsing the expression to the scripting engine and focus on the end result. But if you need to have the AST ( Abstract Syntax Tree ) for the formula expression, then in Python you can use the compiler package (now deprecated) or the new ast module.
PHP's eval function can be dangerous to use if you ask the user to supply you the formula. A user can type calls to undesired functions that have undesired side effects. Python's eval function has similar problems. But Python's eval function makes it easy to define the context and limit access to other Python functions, thus it is possible to secure it.
Evaluating a math expression that the user provides as input is a challenge for most programmers using compiled languages such as C, C++, C#, Java, Delphi. There are math parsers to evaluate expressions in these languages. However, for scripted languages, there is an easier way.
eval(expression[, globals[, locals]])¶
This is the Python's eval function. The arguments are a string and optional globals and locals. If provided, globals must be a dictionary. If provided, locals can be any mapping object.
The expression argument is parsed and evaluated as a Python expression (technically speaking, a condition list) using the globals and locals dictionaries as global and local namespace. If the globals dictionary is present and lacks ‘__builtins__’, the current globals are copied into globals before expression is parsed. This means that expression normally has full access to the standard __builtin__ module and restricted environments are propagated. If the locals dictionary is omitted it defaults to the globals dictionary. If both dictionaries are omitted, the expression is executed in the environment where eval() is called. Thus, in order to make a secure call to eval() function, a developer needs to pass in globals and locals parameters that only contain the list of functions and variables that the user is allowed to invoke.