Allow eval() to evaluate only arithmetic expressions and certain functions

Question:

I have a calculator that uses the eval() function to evaluate expressions, but I am aware of the fact that using eval() is dangerous as it can be used to run arbitrary code on the machine.

So, I want it to only be able to evaluate arithmetic expressions and certain defined functions (imported from another file).

consolecalc.py:

from mymathmodule import *
import time
while True:
    try:   
       Choose = '''Choose your function:
       1: Percentage calculator
       2: Factorial calculator
       3: Basic arithmetics (+-*/)
       '''
       for character in Choose:
        print(character, end="", flush=True)
        time.sleep(0.006)
       a = int(input(':'))
       if a == 1:
           percentagecalc()
       elif a == 2:
           factorialcalc()
       elif a == 3:
           calc = input("Enter Expression:")
           print("Expression equals:",eval(calc))
       else:
           print("nOops! Error.  Try again...") 
       time.sleep(0.6)
    except:
       print("nOops! Error.  Try again...")    
       time.sleep(0.6)

The defined functions are present in mymathmodule.py and I only want eval() to be able to evaluate those along with basic arithmetic expressions

I would also like to know if there are any alternatives to eval() that could do this for me…

Asked By: SK-the-Learner

||

Answers:

You can pass the global and local namespace to eval() as a dict. If the globals contain __builtins__ none of the normal builtin functions can be called from the passed string. You can also use this to provide your own functions, e.g.

globs = {
  "__builtins__": {},
  "sqrt": my_sqrt_fun
}

If you pass that to eval then sqrt in the input will call my_sqrt_fun

eval("3 + sqrt(3)", globs)

Passing e.g. exec will raise a NameError, so no arbitrary code can be executed this way.

Answered By: Emanuel P
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.