python eval和其替代函数ast.literal_eval方法

本文详细介绍了Python中的eval函数及其潜在的安全风险,并对比介绍了更安全的ast.literal_eval方法,通过实例展示了如何使用这两种方法将字符串转换为Python的数据结构。

一、eval函数

原文链接:https://blog.youkuaiyun.com/sinat_33924041/article/details/88350569
eval()官方文档里面给出来的功能解释是:将字符串string对象转化为有效的表达式参与求值运算返回计算结果。


>>> s='8*8'
>>> eval(s)
64
>>> eval('2+5*4')
22
>>> x=1
>>> y=4
>>> eval('x+y')
5
>>> eval('98.9')
98.9
>>> eval('9.9\n')
9.9
>>> eval('9.9\n\t\r  \t\r\n')
9.9

最有用的一个是eval可以将字符串转换成字典,列表,元组


>>> l = "[2,3,4,5]"
>>> ll=eval(l)
>>> ll
[2, 3, 4, 5]
>>> type(ll)
<type 'list'>
>>> d="{'name':'python','age':20}"
>>> dd=eval(d)
>>> type(dd)
<type 'dict'>
>>> dd
{'age': 20, 'name': 'python'}
>>> t='(1,2,3)'
>>> tt=eval(t)
>>> type(tt)
<type 'tuple'>
>>> tt
(1, 2, 3)
————————————————
原文链接:https://blog.csdn.net/sinat_33924041/article/details/88350569

eval()函数功能强大,但也很危险,若程序中有以下语句: s=input(‘please input:’) print (eval(s))
下面举几个被恶意用户使用的例子:
1、运行程序,如果用户恶意输入:
eval(“import(‘os’).system(‘ls -l’)”)
2、运行程序,如果用户恶意输入:
eval(“open(‘a.txt’).read()”)
如果,当前目录中恰好有一个文件,名为a.txt,则恶意用户变读取到了文件中的内容。
3、运行程序,如果用户恶意输入
如果,当前目录中恰好有一个文件,名为a.txt,则恶意用户删除了该文件。/q :指定静音状态。不提示您确认删除
eval(“import(‘os’).system(‘rm -rf a.txt’)”)

二、ast.literal_eval方法

ast.literal_eval是python针对eval方法存在的安全漏洞而提出的一种安全处理方式。
简单点说ast模块就是帮助Python应用来处理抽象的语法解析的。而该模块下的literal_eval()函数:则会判断需要计算的内容计算后是不是合法的Python类型,如果是则进行运算,否则就不进行运算。
比如下面查看系统文件的操作就会被拒绝,而只会执行合法的python类型,从而大大降低了系统的危险性

import ast

res = ast.literal_eval('1 + 1')
print(res)
# 2

res = ast.literal_eval('[1, 2, 3, 4]')
print(type(res))
# <class 'list'>

print(res)
# [1, 2, 3, 4]


res = ast.literal_eval("__import__('os').system('ls')")
# 报错如下:
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/didi/.pyenv/versions/3.6.4/lib/python3.6/ast.py", line 85, in literal_eval
    return _convert(node_or_string)
  File "/Users/didi/.pyenv/versions/3.6.4/lib/python3.6/ast.py", line 84, in _convert
    raise ValueError('malformed node or string: ' + repr(node))
ValueError: malformed node or string: <_ast.Call object at 0x10e63ca58>

# 所以出于安全考虑,对字符串进行类型转换的时候,最好使用ast.literal_eval()
`ast.literal_eval()` 是 Python 标准库 `ast` 中的一个函数,用于安全地解析字符串形式的 Python 字面量表达式。它支持的字面量包括字符串、数字、元组、列表、字典、布尔值 `None`。相比 `eval()`,`ast.literal_eval()` 不会执行任意代码,因此更适合用于解析不可信来源的数据[^1]。 ### 使用方式 该函数的基本使用方法如下: ```python import ast result = ast.literal_eval(node_or_string) ``` 其中参数 `node_or_string` 可以是一个字符串,也可以是一个抽象语法树(AST)节点。若为字符串,它会被解析为一个 Python 字面量表达式。 #### 示例代码: ```python import ast # 解析字符串形式的列表 data = "[1, 2, 3]" parsed_list = ast.literal_eval(data) print(parsed_list) # 输出: [1, 2, 3] # 解析字符串形式的字典 data = "{'name': 'Alice', 'age': 30}" parsed_dict = ast.literal_eval(data) print(parsed_dict) # 输出: {'name': 'Alice', 'age': 30} # 解析字符串形式的布尔值 data = "True" parsed_bool = ast.literal_eval(data) print(parsed_bool) # 输出: True ``` ### 常见错误与限制 1. **SyntaxError**: 如果输入字符串不是有效的 Python 字面量表达式,`ast.literal_eval()` 会抛出 `SyntaxError` 异常。 ```python ast.literal_eval("my_function()") # 抛出 SyntaxError ``` 2. **ValueError**: 如果解析的节点包含非字面量结构(如函数调用或变量引用),该函数将抛出 `ValueError`。 ```python ast.literal_eval("[1, lambda x: x]") # 抛出 ValueError ``` 3. **类型限制**: 该函数仅支持基本的字面量类型,不支持解析自定义对象或复杂的表达式结构。 ```python ast.literal_eval("MyClass()") # 抛出 ValueError ``` 4. **性能问题**: 对于大规模数据结构或频繁调用的场景,`ast.literal_eval()` 的性能可能不如专用的解析器或 JSON 解析器(如 `json.loads()`)。 ### 安全性 `ast.literal_eval()` 的设计初衷是提供一个比 `eval()` 更安全的替代方案。`eval()` 可以执行任意表达式,存在严重的安全隐患,尤其是在处理用户输入时。而 `ast.literal_eval()` 仅限于解析字面量,因此不会执行潜在的恶意代码。 ### 替代方案 - **JSON**: 若数据格式为 JSON,推荐使用 `json` 模块中的 `json.loads()`,其性能通常优于 `ast.literal_eval()`。 - **pickle**: 对于复杂对象的序列化与反序列化,可以使用 `pickle` 模块,但需注意其安全性问题。 - **自定义解析器**: 对于特定格式的数据,可编写自定义解析器以获得更高的灵活性性能。 ### 适用场景 `ast.literal_eval()` 适用于以下场景: - 解析配置文件中的字面量数据。 - 将字符串形式的字面量转换为 Python 对象。 - 在安全性要求较高的环境中替代 `eval()`。 ### 示例错误处理 为了确保程序的健壮性,建议在使用 `ast.literal_eval()` 时进行异常处理: ```python import ast try: result = ast.literal_eval("invalid syntax") except (SyntaxError, ValueError) as e: print(f"Error during parsing: {e}") ``` ### 总结 `ast.literal_eval()` 是一个强大而安全的工具,适用于解析字符串形式的 Python 字面量表达式。尽管它在某些方面存在性能限制,但在安全性要求较高的场景下,它仍然是首选方案。对于更复杂的需求,建议结合其他模块或工具进行处理。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值