📜  Python中的评估

📅  最后修改于: 2022-05-13 01:55:02.723000             🧑  作者: Mango

Python中的评估

Python eval()函数解析表达式参数并将其评估为Python表达式并在程序中运行Python表达式(代码)。

Python eval() 语法

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 有时也用于需要计算数学表达式的应用程序。这比编写表达式解析器要容易得多。