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…
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.
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…
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.