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:Usersasuski 的目录
 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-f47bhg2asuski
37 0
View Code

怎么避免安全问题?

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-/

 

原文地址:https://www.cnblogs.com/hey-jacky/p/9544067.html