关于python:python冷知识之eval的用法

68次阅读

共计 2840 个字符,预计需要花费 8 分钟才能阅读完成。

eval()语法及应用

eval()办法会解析传入该办法的表达式,并且会在程序中运行解析后的表达式。换句话说,它会将一个字符串解析成代码来执行。


STNTAX
eval(expression, GLOBALS=None, LOCALS=None)

  • expression: 传入的表达式
  • GLOBALS: 全局办法或者变量的字典
  • LOCALS: 部分办法或者变量的字典

该办法返回表达式执行的后果。
接下来咱们来创立表达式并运行程序来评估该表达式。


USAGE

user_expr = raw_input("请输出一个对于变量 a 的表达式:")
a = int(raw_input("请输出变量 a 的值:"))
result = eval(user_expr)
print("result = {}".format(result))

OUTPUT

请输出一个对于变量 a 的表达式: a ** 2 + 1
请输出变量 a 的值: 3
result = 10

Security Issue With eval()
假如你导入了 os 模块,os 模块提供了一种快捷的形式来操作诸如读写文件这样的操作系统函数。如果你容许用户应用 eval(input())的形式输出一个值,用户可能会输出扭转系统文件的命令,甚至会输出像 os.system('rm -rf *') 这样的命令删除整个系统文件。那么,在你的代码中应用 eval(input())来检查用户能够应用的办法和变量不失为一个好主见,你能够应用 dir()办法来查看哪些办法和变量是可用的。

from math import *
print(eval('dir()'))

Output

['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'comb', 'copysign', 'cos', 'cosh', 'degrees', 'dist', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'isqrt', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'os', 'perm', 'pi', 'pow', 'prod', 'radians', 'remainder', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc']

在 eval()中限度可用办法和变量的应用

大多数状况下,在 expression 中应用的办法和变量都不是必须的,甚至会造成安全漏洞。你可能须要限度这些办法和变量的应用,你能够通过像 eval() 中传入 globalslocals参数来达到这一目标。


1. 省略 globals 和 locals 参数

如果 globalslocals参数都被省略掉,那么 expression 会在以后范畴内执行,你能够应用上面的办法来查看可用的办法和变量

print(eval(dir()))

2. 只传入 globals 参数

globals参数和 locals 参数 (字典) 别离作用于全局变量和局部变量。如果省略了 locals 字典,那么其默认值是 globals 字典。意思就是,globals字典会同时作用于全局变量和局部变量。

你能够应用 python 的内置办法 globals()和 locals()来别离查看以后的全局变量和局部变量。


3. 传入一个空字典作为 globals 参数
from math import *
print(eval('dir()', {}))

# 上面的代码会抛出异样
print(eval('sqrt(25)', {}))

Output

['__builtins__']
Traceback (most recent call last):
  File "<string>", line 5, in <module>
    print(eval('sqrt(25)', {}))
  File "<string>", line 1, in <module>
NameError: name 'sqrt' is not defined

如果你传入一个空字典作为 globals 参数,那么只有 __builtins__ 办法是可用的,即便咱们导入了 math 模块,expression也不能拜访任何 math 模块提供的办法。


4. 指定某些办法可用
from math import *
print(eval('dir()', {'sqrt': sqrt, 'pow': pow}))

Output

['__builtins__', 'pow', 'sqrt']

在这里,expression 只能应用 sqrt()、pow()以及__builtins__办法。当然,你也能够依据你的爱好来扭转可用办法的名字:

from math import *
names = {'square_root': sqrt, 'power': pow}
print(eval('dir()', names))

# 在表达式中应用别名
print(eval('square_root(9)', names))

Output

['__builtins__', 'power', 'square_root']
3.0

在下面的例子中,如果尝试间接应用 sqrt() 办法,程序会抛出谬误。


5. 限度 built-ins 的应用

你能够通过上面的办法限度 expression__builtins__的应用:

eval(expression, {'__builtins__: None})

6. 传入 globals 和 globals 参数
from math import *

a = 169
print(eval('sqrt(a)', {'__builtins__': None}, {'a': a, 'sqrt': sqrt}))

Output

13.0

在这个例子中,expression能并且只能应用 sqrt() 办法和变量a,其它的所有办法和变量都不可能应用。


通过 globalslocals参数的传递来限度 eval() 的用法能够让你的代码更加平安,尤其是在应用用户通过 input() 办法给 eval() 的时候。

有时候,即便限度 eval()可应用的办法和变量也不是平安的,当一个对象和它的的办法是可拜访的,简直能够做任何事,这时候惟一平安的办法就是验证用户输出的有效性。

整顿自:

  • https://www.tutorialspoint.com/python-eval
  • https://www.programiz.com/python-programming/methods/built-in/eval

正文完
 0