是否存在可安全对简单表达式求值的Python模块?
可选方案1:使用第三方库 simpleeval(最便捷)
这是专门为安全表达式求值设计的轻量库,默认屏蔽了所有危险执行逻辑,原生支持比较运算、算术运算、逻辑运算等常用简单表达式需求,不需要自己处理语法解析逻辑。
- 安装方式:
pip install simpleeval - 使用示例:
from simpleeval import simple_eval # 基础比较运算 print(simple_eval("1 > 0")) # 输出 True # 支持传入自定义变量 print(simple_eval("a + b >= 10", names={"a": 3, "b": 8})) # 输出 True # 支持逻辑运算 print(simple_eval("1 < 2 and 3 > 2")) # 输出 True
它默认禁用了函数调用、属性访问、导入等危险操作,不会出现eval的代码注入风险,足够覆盖绝大多数简单表达式求值场景。
可选方案2:基于ast自定义解析(无第三方依赖)
如果不想引入额外依赖,可以自己基于ast模块做白名单控制,只允许你需要的语法节点类型,示例实现如下:
import ast import operator # 配置允许的运算符白名单,可按需扩展 ALLOWED_OPS = { # 算术运算符 ast.Add: operator.add, ast.Sub: operator.sub, ast.Mult: operator.mul, ast.Div: operator.truediv, # 比较运算符 ast.Gt: operator.gt, ast.Lt: operator.lt, ast.Eq: operator.eq, ast.GtE: operator.ge, ast.LtE: operator.le, ast.NotEq: operator.ne, # 逻辑运算符 ast.And: lambda a,b: a and b, ast.Or: lambda a,b: a or b, } def safe_eval(expr: str): ast_root = ast.parse(expr, mode='eval').body def parse_node(node): if isinstance(node, ast.Constant): return node.value elif isinstance(node, ast.BinOp): op_cls = type(node.op) if op_cls not in ALLOWED_OPS: raise ValueError(f"不支持的运算符:{op_cls.__name__}") return ALLOWED_OPS[op_cls](parse_node(node.left), parse_node(node.right)) elif isinstance(node, ast.Compare): left_val = parse_node(node.left) for op, comp_node in zip(node.ops, node.comparators): op_cls = type(op) if op_cls not in ALLOWED_OPS: raise ValueError(f"不支持的运算符:{op_cls.__name__}") comp_val = parse_node(comp_node) if not ALLOWED_OPS[op_cls](left_val, comp_val): return False left_val = comp_val return True elif isinstance(node, ast.BoolOp): op_cls = type(node.op) if op_cls not in ALLOWED_OPS: raise ValueError(f"不支持的逻辑运算符:{op_cls.__name__}") res = parse_node(node.values[0]) for val_node in node.values[1:]: res = ALLOWED_OPS[op_cls](res, parse_node(val_node)) return res else: raise ValueError(f"不支持的语法节点:{type(node).__name__}") return parse_node(ast_root) # 测试 print(safe_eval("1 > 0")) # 输出 True print(safe_eval("2 + 3 * 5 > 10")) # 输出 True
这种方案完全可控,你可以根据自己的需求扩展允许的语法类型,不会有额外的安全风险。
内容的提问来源于stack exchange,提问作者sasano8
相关产品推荐
相关产品推荐

