Python中的评估
Python eval()函数解析表达式参数并将其评估为Python表达式并在程序中运行Python表达式(代码)。
Python eval() 语法
eval(expression, globals=None, locals=None)
Python eval() 参数
- 表达式:此字符串被解析并评估为Python表达式
- globals(可选):一个字典,用于指定可用的全局方法和变量。
- locals(可选):另一个字典,用于指定可用的本地方法和变量。
Python eval() 示例
示例 1:演示使用 eval() 的示例
让我们借助一个简单的Python程序来探索它。 function_creator是一个评估用户创建的数学函数的函数。
Python3
from math import *
def secret_function():
return "Secret key is 1234"
def function_creator():
# expression to be evaluated
expr = input("Enter the function(in terms of x):")
# variable used in expression
x = int(input("Enter the value of x:"))
# evaluating expression
y = eval(expr)
# printing evaluated result
print("y = {}".format(y))
if __name__ == "__main__":
function_creator()
Python3
evaluate = 'x*(x+1)*(x+2)'
print(evaluate)
print(type(evaluate))
x = 3
print(type(x))
expression = eval(evaluate)
print(expression)
print(type(expression))
Python3
from math import *
def secret_function():
return "Secret key is 1234"
def function_creator():
# expression to be evaluated
expr = input("Enter the function(in terms of x):")
# variable used in expression
x = int(input("Enter the value of x:"))
# passing variable x in safe dictionary
safe_dict['x'] = x
# evaluating expression
y = eval(expr, {"__builtins__": None}, safe_dict)
# printing evaluated result
print("y = {}".format(y))
if __name__ == "__main__":
# list of safe methods
safe_list = ['acos', 'asin', 'atan', 'atan2', 'ceil', 'cos',
'cosh', 'degrees', 'e', 'exp', 'fabs', 'floor',
'fmod', 'frexp', 'hypot', 'ldexp', 'log', 'log10',
'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt',
'tan', 'tanh']
# creating a dictionary of safe methods
safe_dict = dict([(k, locals().get(k, None)) for k in safe_list])
function_creator()
输出:
Enter the function(in terms of x):x*(x+1)*(x+2)
Enter the value of x:3
y = 60
让我们稍微分析一下代码:
- 上述函数将变量x中的任何表达式作为输入。
- 然后用户必须输入x的值。
- 最后,我们使用eval()内置函数通过将expr作为参数传递来评估Python表达式。
示例 2:使用 eval函数的数学运算
Python3
evaluate = 'x*(x+1)*(x+2)'
print(evaluate)
print(type(evaluate))
x = 3
print(type(x))
expression = eval(evaluate)
print(expression)
print(type(expression))
x*(x+1)*(x+2)
60
eval 的漏洞问题
我们当前版本的function_creator有一些漏洞。用户可以轻松地暴露程序中的隐藏值或调用危险函数,因为 eval 将执行传递给它的任何内容。
例如,如果您这样输入:
Enter the function(in terms of x):secret_function()
Enter the value of x:0
你会得到输出:
y = Secret key is 1234
另外,请考虑在Python程序中导入os模块时的情况。 os 模块提供了一种可移植的方式来使用操作系统功能,例如读取或写入文件。一个命令可以删除系统中的所有文件。当然,在大多数情况下(如桌面程序),用户只能编写自己的Python脚本,但在某些应用程序(如 Web 应用程序、信息亭计算机)中,这可能是一种风险!
解决方案是将eval限制在我们想要提供的函数和变量上。
使 eval 安全
eval函数具有显式传递它可以访问的函数或变量列表的功能。我们需要以字典的形式将它作为参数传递。
Python3
from math import *
def secret_function():
return "Secret key is 1234"
def function_creator():
# expression to be evaluated
expr = input("Enter the function(in terms of x):")
# variable used in expression
x = int(input("Enter the value of x:"))
# passing variable x in safe dictionary
safe_dict['x'] = x
# evaluating expression
y = eval(expr, {"__builtins__": None}, safe_dict)
# printing evaluated result
print("y = {}".format(y))
if __name__ == "__main__":
# list of safe methods
safe_list = ['acos', 'asin', 'atan', 'atan2', 'ceil', 'cos',
'cosh', 'degrees', 'e', 'exp', 'fabs', 'floor',
'fmod', 'frexp', 'hypot', 'ldexp', 'log', 'log10',
'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt',
'tan', 'tanh']
# creating a dictionary of safe methods
safe_dict = dict([(k, locals().get(k, None)) for k in safe_list])
function_creator()
现在,如果我们尝试运行上述程序,例如:
Enter the function(in terms of x):secret_function()
Enter the value of x:0
我们得到输出:
NameError: name 'secret_function' is not defined
让我们一步一步分析上面的代码:
- 首先,我们创建一个我们希望允许的方法列表作为safe_list 。
- 接下来,我们创建一个安全方法字典。在这个字典中,键是方法名,值是它们的本地命名空间。
safe_dict = dict([(k, locals().get(k, None))
for k in safe_list])
- locals()是一个内置方法,它返回一个字典,该字典将本地范围内的所有方法和变量与其命名空间进行映射。
safe_dict['x'] = x
在这里,我们也将局部变量x添加到 safe_dict。 eval函数将识别除x以外的任何局部变量。
- eval接受本地和全局变量的字典作为参数。因此,为了确保没有任何内置方法可用于eval表达式,我们还传递了另一个字典以及safe_dict ,如下所示:
y = eval(expr, {"__builtins__":None}, safe_dict)
因此,通过这种方式,我们使我们的eval函数免受任何可能的黑客攻击!
评估的用途
正如我们上面探讨的那样,由于安全原因, eval并没有太多使用。
尽管如此,它在某些情况下仍然派上用场,例如:
- 您可能希望使用它来允许用户输入他们自己的“scriptlet”:小表达式(甚至是小函数),可用于自定义复杂系统的行为。
- eval 有时也用于需要计算数学表达式的应用程序。这比编写表达式解析器要容易得多。