英文:
Allow eval() to evaluate only arithmetic expressions and certain functions
问题
我有一个计算器,它使用`eval()`函数来评估表达式,但我意识到使用`eval()`是危险的,因为它可以用来在计算机上运行任意代码。
因此,我希望它只能评估算术表达式和某些定义好的函数(从另一个文件中导入)。
consolecalc.py:
```py
from mymathmodule import *
import time
while True:
try:
Choose = '''选择你的功能:
1:百分比计算器
2:阶乘计算器
3:基本算术(+-*/)
'''
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("输入表达式:")
print("表达式结果为:",eval(calc))
else:
print("\n糟糕!出错了。请重试...")
time.sleep(0.6)
except:
print("\n糟糕!出错了。请重试...")
time.sleep(0.6)
定义的函数在mymathmodule.py中,我只希望eval()
能够评估这些函数以及基本算术表达式。
我还想知道是否有任何替代eval()
的方法可以为我做到这一点...
英文:
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...
答案1
得分: 2
你可以将全局和本地命名空间作为字典传递给eval()
。如果全局命名空间包含__builtins__
,则无法从传递的字符串中调用任何正常的内置函数。您还可以使用这种方式提供您自己的函数,例如:
globs = {
"__builtins__": {},
"sqrt": my_sqrt_fun
}
如果将其传递给eval
,那么输入中的sqrt
将调用my_sqrt_fun
。
eval("3 + sqrt(3)", globs, {})
当使用河马操作符在表达式内发生赋值时,它将设置在本地字典中,因此使用空字典。您可以使用这种方式允许设置变量,但为了防止用户覆盖任何内容,只使用该字典来实现此目的。
例如,传递exec
将引发NameError
,因此不能以这种方式执行任意代码。
英文:
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, {})
When an assignment occurs within the expression using the walrus operator, it will be set in the local dictionary, hence the empty dictionary. You could use this allow variables to be set, but to prevent users from overwriting anything, use that dictionary only for that purpose.
Passing e.g. exec
will raise a NameError
, so no arbitrary code can be executed this way.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论