python eval()
eval(expression, globals=None, locals=None)
功能:将字符串str当成有效的表达式来求值并返回计算结果。
语法: eval(source[, globals[, locals]]) -> value
参数:
source:一个Python表达式或函数compile()返回的代码对象
globals:可选。必须是dictionary
locals:可选。任意map对象
python是用命名空间来记录变量的轨迹的,命名空间是一个dictionary,键是变量名,值是变量值。
当一行代码要使用变量 x 的值时,Python 会到所有可用的名字空间去查找变量,按照如下顺序:
1)局部名字空间 - 特指当前函数或类的方法。如果函数定义了一个局部变量 x, 或一个参数 x,Python 将使用它,然后停止搜索。
2)全局名字空间 - 特指当前的模块。如果模块定义了一个名为 x 的变量,函数或类,Python 将使用它然后停止搜索。
3)内置名字空间 - 对每个模块都是全局的。作为最后的尝试,Python 将假设 x 是内置函数或变量。
python的全局名字空间存储在一个叫globals()的dict对象中;局部名字空间存储在一个叫locals()的dict对象中。我们可以用print (locals())来查看该函数体内的所有变量名和变量值。
eval()使用原因:
1)在编译语言里要动态地产生代码,基本上是不可能的,但动态语言是可以,意味着软件已经部署到服务器上了,但只要作很少的更改,只好直接修改这部分的代码,就可立即实现变化,不用整个软件重新加载。
2)在machin learning里根据用户使用这个软件频率,以及方式,可动态地修改代码,适应用户的变化。
eval()用法:将字符串str当成有效的表达式来求值并返回计算结果。
example:
>>> a = 1 >>> g = {"a":10} >>> eval("a-1", g) 9
1 x = 1 2 y = 1 3 def g(): 4 x = 2 5 y = 2 6 num1 = eval("x+y",globals()) #全局的x,y 7 num2 = eval("x+y",globals(),locals())#函数的x,y 8 print ('num1:%s'%num1) 9 print ('num2:%s'%num2) 10 #查看全局和局部的x和y 11 print ('局部变量x:%s'%locals()["x"]) 12 print ('全局变量x:%s'%globals()["x"]) 13 print ('局部变量y:%s'%locals()["y"]) 14 print ('全局变量y:%s'%globals()["y"]) 15 16 g() 17 #运行结果 18 num1:2 19 num2:4 20 局部变量x:2 21 全局变量x:1 22 局部变量y:2 23 全局变量y:1
addition:locals()对象的值不能修改,globals()对象的值可以修改
1 z=0 2 def f(): 3 z = 1 4 print (locals()) #局部 5 locals()["z"] = 2 #尝试修改局部变量z 6 print (locals()) 7 f() 8 9 globals()["z"] = 2 #修改全局变量z 10 print (z) 11 12 #运行结果 13 {'z': 1} 14 {'z': 1} 15 2
可以看出,两个print (locals())的结果是一样的,说明没有修改成功。而print (z)的值是2,说明修改成功了
eval()妙用:可以把list,tuple,dict和string相互转化。
1 #####-字符串转换成列表-###### 2 >>> a = "['jiege','weige',111,[21]]" 3 >>> type(a) 4 <class 'str'> 5 >>> b = eval(a) 6 >>> print(b) 7 ['jiege', 'weige', 111, [21]] 8 >>> type(b) 9 <class 'list'>
1 #####-字符串转换成字典-###### 2 >>> a="{'x':34,y:'haha'}" 3 >>> a = "{'x':34,y:'haha'}" 4 >>> b = eval(a) 5 >>> print(b) 6 {'x': 34, 12: 'haha'} 7 >>> print(type(a),type(b)) 8 <class 'str'> <class 'dict'>
1 #####-字符串转换成元组-###### 2 >>> a = "(['hh',65],[90],(65,76))" 3 >>> b = eval(a) 4 >>> print(b) 5 (['hh', 65], [90], (65, 76)) 6 >>> print(type(a),type(b)) 7 <class 'str'> <class 'tuple'>
eval()安全性问题:比如用户恶意输入就会获得当前目录文件
#Windows命令行下的python中执行
1 #Windows命令行下的python中执行 2 >>> eval("__import__('os').system('dir')") 3 驱动器 C 中的卷是 OS 4 卷的序列号是 24F2-B2C9 5 6 C:\Users\asuski 的目录 7 8 2018/08/25 18:51 <DIR> . 9 2018/08/25 18:51 <DIR> .. 10 2017/10/06 09:18 <DIR> .android 11 2018/08/25 18:51 50 .gitconfig 12 2018/03/27 19:34 <DIR> .idlerc 13 2018/04/19 17:49 <DIR> .jssc 14 2018/08/06 16:28 <DIR> .PyCharm2018.2 15 2018/08/16 22:16 <DIR> 3D Objects 16 2018/08/16 22:17 <DIR> Contacts 17 2018/08/26 21:54 <DIR> Desktop 18 2018/08/16 22:17 <DIR> Documents 19 2018/08/16 22:17 <DIR> Downloads 20 2018/08/16 22:17 <DIR> Favorites 21 2018/08/16 22:17 <DIR> Links 22 2018/01/10 22:37 36 mm.cfg 23 2018/08/16 22:17 <DIR> Music 24 2018/02/26 19:51 <DIR> OneDrive 25 2018/08/16 22:17 <DIR> Pictures 26 2018/08/16 22:17 <DIR> Saved Games 27 2018/08/16 22:17 <DIR> Searches 28 2018/08/16 22:17 <DIR> Videos 29 2 个文件 86 字节 30 19 个目录 193,297,190,912 可用字节 31 0 32 >>> import os 33 >>> 'os' in globals() 34 True 35 >>> os.system('whoami') 36 desktop-f47bhg2\asuski 37 0
怎么避免安全问题?
1、自行写检查函数;
2、使用ast.literal_eval
参考
https://docs.python.org/2/library/ast.html
http://python.jobbole.com/82770/
http://code.activestate.com/recipes/496746-restricted-safe-/