Python的eval与exec

1、eval(expression, globals=None, locals=None)
expression:一个简单的表达式,不能是复杂的循环等;
globals: 全局变量,可以在globals中定义expression表达式中需要的变量;
locals: 局部变量,当局部变量和全局变量同时存在时,局部回覆盖全局变量的值;
执行expression,返回expression执行的结果。

>>> a = 100
>>> b = 2000
>>> eval("a+b")
2100
>>> eval("a+b", {"a":10, "b":20})
30
>>> eval("a+b", {"a":10, "b":20}, {"b":50})
60
>>> 

2、exec(obj, globals=None, locals=None)
obj:是个字符串,里面包含了需要执行的代码块;
globals: 全局变量,可以在globals中定义expression表达式中需要的变量;
locals: 局部变量,当局部变量和全局变量同时存在时,局部回覆盖全局变量的值;
执行obj, 返回None。

>>> a = 100
>>> b = 2000
>>> eval("a+b")
2100
>>> exec("a+b", {"a":10, "b":20}, {"b":50})
>>> exec("c = a+b", {"a":10, "b":20}, {"b":50})
>>> exec("print(a+b);print(a*b)", {"a":10, "b":20}, {"b":50})
60
500

eval()与exec()很相似,它们将字符串内容当做有效的代码执行,区别就在于第一个参数。eval的第一个参数是是一个表达式,eval是执行这个表达式并返回其结果;exec的第一个参数是一个代码块,exec就是执行这额代码块,返回None。

3、常用的就是将字符串类型json转为json对象

>>> a = "{'a': [1, 2, 3], 'b': (3, 4)}"
>>> eval(a)
{'a': [1, 2, 3], 'b': (3, 4)}

# exec只是执行,没有返回值,所以要在代码块中指定变量来获取json的值。
>>> a = "b = {'a': [1, 2, 3], 'b': (3, 4)}"
>>> exec(a)
>>> b
{'a': [1, 2, 3], 'b': (3, 4)}

4、慎用 eval()
为什么要慎用 eval() 呢?主要出于安全考虑,对于不可信的数据源,eval 函数很可能会招来代码注入的问题。
比如将用户发过来的数据先使用eval转换(正常情况是json),如果传入“rm -rf ~”,就被删除完了。

直接在eval中调用了系统内置函数

>>> eval("__import__('os').system('whoami')")
*****
0
>>> 

在默认情况下,eval 函数的 globals 参数会隐式地携带__builtins__ ,所以如果想要禁用它,可以显示指定__builtins__为None,从而限制了表达式调用内置模块或属性的能力。

>>> eval("__import__('os').system('whoami')", {'__builtins__': None})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
NameError: name '__import__' is not defined
>>> 

但是这样还是会有很多手段进行攻击,可以看看这边文章:Python eval的常见错误封装及利用原理详解

5、安全使用

1)使用ast.literal_eval,ast.literal() 会先检查表达式内容是否有效合法。它所允许的字面内容如下:

strings, bytes, numbers, tuples, lists, dicts, sets, booleans, None

一旦内容非法,则会报错:

>>> ast.literal_eval("__import__('os').system('whoami')")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/Cellar/python@2/2.7.16/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ast.py", line 80, in literal_eval
    return _convert(node_or_string)
  File "/usr/local/Cellar/python@2/2.7.16/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ast.py", line 79, in _convert
    raise ValueError('malformed string')
ValueError: malformed string
>>> 

2)如果只是转化json,可以用json的函数json.loads等。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值