如何将用户输入的包含and/or的条件字符串转换为Python if判断条件
实现方案
基础版(适合内部可信环境使用)
直接通过正则替换把条件里的指标名映射为row的取值,再用eval执行判断即可,代码量极小,支持任意and/or组合的条件:
import re def match_row(row, condition_str): # 替换所有非逻辑词的独立变量为 row["变量名"] 格式 processed_expr = re.sub( r"\b([a-zA-Z_][a-zA-Z0-9_]*)\b", lambda match: f'row["{match.group(1)}"]' if match.group(1) not in ("and", "or") else match.group(1), condition_str ) return eval(processed_expr)
调用示例
# 示例数据行 row = {"RSI": 35, "MACD": 1.2, "KDJ": 60} # 用户输入的条件 user_condition = "RSI > 30 and MACD > 0 or KDJ < 20" # 直接判断 print(match_row(row, user_condition)) # 输出 True
安全增强版(适合公开对外的场景)
eval本身存在代码注入风险,如果你的程序允许陌生用户输入条件,可以通过AST语法树校验限制只允许合法的判断操作,彻底规避注入风险:
import re import ast def safe_match_row(row, condition_str): # 先做变量替换 processed_expr = re.sub( r"\b([a-zA-Z_][a-zA-Z0-9_]*)\b", lambda match: f'row["{match.group(1)}"]' if match.group(1) not in ("and", "or") else match.group(1), condition_str ) # 解析语法树并校验节点合法性 try: tree = ast.parse(processed_expr, mode="eval") except SyntaxError: raise ValueError("条件格式错误") # 允许出现的语法节点类型,仅保留判断相关的操作 ALLOWED_NODES = ( ast.Expression, ast.Compare, ast.BoolOp, ast.And, ast.Or, ast.Name, ast.Constant, ast.Load, ast.Gt, ast.Lt, ast.GtE, ast.LtE, ast.Eq, ast.NotEq, ast.Subscript, ast.Str ) for node in ast.walk(tree): if not isinstance(node, ALLOWED_NODES): raise ValueError("条件包含非法操作") # 限定执行上下文,仅传入row变量,无全局命名空间 return eval(compile(tree, filename="", mode="eval"), {"row": row}, {})
注意事项
- 如果指标名包含特殊字符(比如空格、短横线),需要调整正则匹配规则适配你的指标命名规范
- 你可以直接将返回的布尔值用到业务逻辑里,不需要额外写
if ... return True的判断,直接return safe_match_row(row, user_input)即可
内容的提问来源于stack exchange,提问作者itisku
相关产品推荐
相关产品推荐

