目录
eval()和exec()两个函数功能相似,可以执行一个字符串形式的python表达式,相当于一个python的解释器。
eval()和exec()的不同在于:eval()执行完要返回结果,而exec()执行完不返回结果。
eval()语法格式:
eval(expression[, globals[,locals]])
exec()语法格式:
exec(expression,globals=None,locals=None)
二者参数一样,参数说明:
返回值:返回表达式计算的结果
⚪ 不使用globals和locals参数:
- print('2*3=',eval('2*3'))
- print('2**3=',eval('2**3'))
- print('pow(3,2)=',eval('pow(3,2)'))
- n=3
- print('n+9=',eval('n+9'))
- n='3'
- print('n*9=',eval('n*9'))
显示结果:
- 2*3= 6
- 2**3= 8
- pow(3,2)= 9
- n+9= 12
- n*9= 333333333
⚪ 使用globals参数:
- dic={}
- dic['b'] = 3
- print(dic.keys())
- exec('a=4',dic)
- print(dic.keys())
显示结果:
- dict_keys(['b'])
- dict_keys(['b', '__builtins__', 'a'])
可以看到,exec(0函数中在作用域dic下执行了a=4的代码。执行完exec()后dic中新生成了两个新的key,分别是a和__builtins__,a是执行语句生成的,__builtins__是系统加入的内置key。
⚪ 使用locals参数:
- a=10
- b=20
- c=30
- g={'a':6,'b':8}
- t={'b':100,'c':10}
- print(eval('a+b+c',g,t))
显示结果:
- 116
- None
g是global全局命名变量,t是local局部命名变量,如果设置了local参数,则使用local,否则使用globals。表达式是a+b+c,t中包含b和c,g中包含a和b,那么a=6,b=100,c=10。b=100是因为要使用t中的变量,不能使用g中的变量。所以最终结果返回116。
从上面的返回结果可以看出,exec()执行完不返回结果,eval()执行完会返回结果。所以exec()中适合放置运行后没有结果的语句,eval()中适合放置有结果返回的语句。
如果eval()中表达式是没有返回值的参数,会报错:SyntaxError: invalid syntax。如:
print(eval('a=2'))
会有以下错误:
- print(eval('a=2'))
- File "
" , line 1 - a=2
- ^
- SyntaxError: invalid syntax
使用python开发服务端程序时,这两个函数使用的比较多。例如,客户端向服务端发送一段字符串代码,服务端无需关心具体的内容,直接跳过exec()和eval()来执行,这样设计可以使服务端与客户端的耦合度更低,系统更易扩展。
但是需要注意的是,使用eval()或是exec()处理请求代码时,这两个啊哈桑农户常常会被黑客利用,称为可以执行系统级命令的入口点,进而来攻击网站。解决方法是:通过设置其命名空间里的可执行函数,限制eval()和exec()的执行范围。
全文参考: