Python中替代eval读取dat文件内容转换为numpy数组的方案咨询
可行的替代方案
方案1:优先调整存储格式(最高效安全)
如果可以修改dat文件的生成逻辑,直接使用numpy原生的序列化格式是最优选择:
- 写文件时调用
np.save('trial.npy', 待存储的数组) - 读文件时直接加载:
import numpy as np x_1 = np.load('trial.npy', allow_pickle=False) y = np.concatenate(x_1)
该方案完全规避字符串解析的安全风险,读写速度远高于文本解析,无需处理字符串匹配逻辑。
方案2:无法修改存储格式时,用AST白名单解析
如果必须保留现有带np.repeat这类numpy调用的文本存储格式,用AST(抽象语法树)白名单机制替代eval,仅允许你指定的合法语法和函数调用,完全拦截恶意代码:
import numpy as np import ast # 配置允许的numpy函数白名单,按需添加你用到的numpy方法 ALLOWED_NP_FUNCS = {'repeat'} def safe_eval_np(expr): # 解析表达式为AST节点 tree = ast.parse(expr, mode='eval') # 遍历所有节点校验合法性 for node in ast.walk(tree): # 允许的节点类型:表达式、列表、数字、常量、属性访问、调用 if isinstance(node, (ast.Expression, ast.List, ast.Num, ast.Constant, ast.Attribute, ast.Call, ast.Load)): # 校验numpy调用是否在白名单 if isinstance(node, ast.Attribute): if node.value.id != 'np' or node.attr not in ALLOWED_NP_FUNCS: raise ValueError(f"非法调用:np.{node.attr} 不在白名单") continue # 其他节点类型直接拦截 raise ValueError(f"非法语法:{type(node).__name__} 不被允许") # 校验通过后执行 return eval(compile(tree, filename='<ast>', mode='eval')) # 适配你原来的读取逻辑 with open('trial.dat', 'r') as f: data = f.readlines() data = [(d+' ')[:d.find('#')].rstrip() for d in data] x_1 = safe_eval_np(data[0]) y = np.concatenate(x_1)
你给出的示例字符串[[1,2,np.repeat(3,1)]]可以正常通过该函数解析,得到和原eval完全一致的结果。如果后续用到其他numpy方法,直接添加到ALLOWED_NP_FUNCS集合即可。
内容的提问来源于stack exchange,提问作者msci
相关产品推荐
相关产品推荐

