
本文介绍如何在 Python 中安全、灵活地解析并执行用户通过 JSON 等外部配置输入的动态条件表达式(如 (Bob.age == Jane.age) || (Bob.age本文介绍如何在 python 中安全、灵活地解析并执行用户通过 json 等外部配置输入的动态条件表达式(如 `(bob.age == jane.age) || (bob.age
在数据报告、规则引擎或低代码配置场景中,常需让非开发人员通过简单语法(如 JSON 或 DSL)定义业务逻辑条件。例如,给定人员属性表:
data = { "Bob": {"age": 47}, "Bill": {"age": 44}, "Jane": {"age": 36}, "Steve": {"age": 22} }用户希望在 JSON 配置中声明类似
(Bob.age == Jane.age) or (Bob.age 的布尔表达式,并由程序动态求值。⚠️ 切勿直接使用
eval()
虽然eval("(Bob.age == Jane.age) or (Bob.age 在技术上可行,但它会执行任意 Python 代码,存在严重安全漏洞(如 <code>eval("__import__('os').system('rm -rf /')"))。✅ 推荐方案:
simpleeval(轻量、安全、专为表达式设计)
安装:pip install simpleeval使用示例:
from simpleeval import SimpleEval # 构建安全上下文:仅暴露允许的对象和操作符 context = { "Bob": data["Bob"], "Bill": data["Bill"], "Jane": data["Jane"], "Steve": data["Steve"] } # 支持点号访问(需自定义函数) def safe_getattr(obj, attr): if isinstance(obj, dict): return obj.get(attr) return getattr(obj, attr, None) se = SimpleEval() se.functions['getattr'] = safe_getattr # 更实用的方式:预展开嵌套属性(推荐) flat_context = { "Bob_age": data["Bob"]["age"], "Bill_age": data["Bill"]["age"], "Jane_age": data["Jane"]["age"], "Steve_age": data["Steve"]["age"] } # 用户表达式(注意:JSON 中需用标准 Python 语法,而非 JS 的 ||) user_expr = "(Bob_age == Jane_age) or (Bob_age < Bill_age)" result = se.eval(user_expr, names=flat_context) # → False print(result) # False? 进阶建议
立即学习“Python免费学习笔记(深入)”;
- 将
name.field转换为name_field的预处理逻辑可封装为工具函数,提升可维护性;- 对用户输入做语法校验(
se.eval()抛出InvalidExpression异常时捕获并返回友好提示);- 如需支持更复杂逻辑(函数调用、列表推导),可考虑
numexpr(数值计算场景)或asteval(扩展 AST 解析);- 永远避免将用户输入拼接到
eval()/exec()字符串中——这是不可妥协的安全红线。总结:动态条件求值不是“是否能做”,而是“如何安全、可维护地做”。选用
simpleeval+ 扁平化上下文是兼顾简洁性、安全性与可读性的最佳实践。


















