
本文介绍如何在 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 代码,存在严重安全漏洞(如 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 <p>? <strong>进阶建议</strong> </p>
- 将
name.field转换为name_field的预处理逻辑可封装为工具函数,提升可维护性; - 对用户输入做语法校验(
se.eval()抛出InvalidExpression异常时捕获并返回友好提示); - 如需支持更复杂逻辑(函数调用、列表推导),可考虑
numexpr(数值计算场景)或asteval(扩展 AST 解析); - 永远避免将用户输入拼接到
eval()/exec()字符串中——这是不可妥协的安全红线。
总结:动态条件求值不是“是否能做”,而是“如何安全、可维护地做”。选用 simpleeval + 扁平化上下文是兼顾简洁性、安全性与可读性的最佳实践。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











