0

0

Python 中安全高效地解析并验证字典键值对的自定义条件表达式

心靈之曲

心靈之曲

发布时间:2026-03-15 17:01:04

|

404人浏览过

|

来源于php中文网

原创

本文介绍一种基于正则解析与 operator 模块的安全、可扩展方案,用于将用户输入的类 Python 条件字符串(如 'a > 5, 0 < (cd) < 6')动态映射为对字典的实际逻辑校验,避免 eval() 风险,支持链式比较、多种数据类型及嵌套操作。

本文介绍一种基于正则解析与 operator 模块的安全、可扩展方案,用于将用户输入的类 python 条件字符串(如 `'a > 5, 0

在实际开发中,常需根据用户输入的灵活条件(如 'a > 5, 0 < (cd) < 6, ef < 35')动态校验字典内容是否全部满足。虽然可手动 split(',') 后逐条提取键、运算符和值再比对,但该方式易出错、难以支持链式比较(如 0 < x < 6),且直接使用 eval() 存在严重安全风险(任意代码执行)。本文提供一个安全、健壮、可扩展的纯 Python 解决方案。

核心设计思路

本方案不依赖外部库(如 Pandas),而是通过以下三步实现优雅解析:

In3D
In3D

把真人变成化身,创建逼真且可自定义的虚拟角色

下载
  1. 运算符映射:使用 operator 模块将字符串运算符('>', '!=' 等)映射为可调用函数;
  2. 结构化解析:利用正则表达式精准切分运算符与操作数,区分字典键名(如 'a'、'(cd)')与字面量(数字、字符串、布尔值、None);
  3. 类型自动推导:cast() 函数智能识别并转换数值(int/float)、字符串(带引号)、布尔值及 None,确保类型安全比较。

完整实现代码

import operator
import re

# 运算符到函数的映射(支持常见比较操作)
operators = {
    '<=': operator.le,
    '>=': operator.ge,
    '>':  operator.gt,
    '<':  operator.lt,
    '==': operator.eq,
    '!=': operator.ne
}

# 构建正则:匹配任意已注册运算符(转义特殊字符)
_oper = '|'.join(map(re.escape, operators.keys()))
oper_pattern = re.compile(fr'\s*({_oper})\s*').split
number_pattern = re.compile(r'-?\d*(\.\d+)?').fullmatch
string_pattern = re.compile(r'("|\')(?P<str>.*)\1').fullmatch


def cast(value: str) -> float | int | bool | str | None:
    """将字符串字面量安全转换为对应 Python 类型"""
    v = value.strip()
    lower_v = v.lower()

    if lower_v in ('true', 'false'):
        return lower_v == 'true'
    elif m := string_pattern(v):
        return m.group('str')
    elif m := number_pattern(v):
        return float(v) if '.' in v else int(v)
    elif v == 'None':
        return None
    else:
        raise ValueError(f"无法解析字面量: '{value}'")


def check_conditions(data: dict, conditions: str) -> bool:
    """
    校验字典 data 是否满足所有 conditions 中的逻辑条件

    Args:
        data: 待校验的字典(键为字符串,值为任意类型)
        conditions: 逗号分隔的条件字符串,例如 'a > 5, 0 < (cd) < 6, ef == 35'

    Returns:
        bool: 所有条件均满足返回 True,否则 False

    Raises:
        ValueError: 条件语法错误或无法解析字面量时抛出
    """
    all_results = []

    for cond in conditions.split(','):
        cond = cond.strip()
        if not cond:
            continue

        values, ops = [], []
        # 按运算符切分,交替获取操作数和运算符
        tokens = oper_pattern(cond)

        for token in tokens:
            token = token.strip()
            if not token:
                continue
            if token in operators:
                ops.append(operators[token])
            else:
                # 尝试从字典取值;若不存在,则尝试解析为字面量
                val = data.get(token)
                if val is None and token not in data:
                    val = cast(token)
                values.append(val)

        # 验证结构:n 个运算符必须对应 n+1 个操作数
        if len(values) != len(ops) + 1:
            raise ValueError(f"条件格式错误: '{cond}' — 运算符与操作数数量不匹配")

        # 执行链式比较:[v0, v1, v2] + [op0, op1] → op0(v0,v1) and op1(v1,v2)
        chain_ok = True
        for i in range(len(ops)):
            try:
                if not ops[i](values[i], values[i + 1]):
                    chain_ok = False
                    break
            except TypeError as e:
                raise TypeError(f"类型不兼容比较 '{values[i]} {list(operators.keys())[list(operators.values()).index(ops[i])]} {values[i+1]}': {e}")

        all_results.append(chain_ok)

    return all(all_results)

使用示例

# 示例数据
data = {
    'a': 25,
    'ab': 3.3,
    '(cd)': 4,
    'ef': 35,
    'gh': 12.2,
    'ij': "hello",
    'kl': False,
    'mn': None
}

# 多种条件组合(支持链式、混合类型、引号字符串)
conditions = "a > 5, 0 < (cd) < 6, ef < 35, ij == 'hello', mn == None"

if check_conditions(data, conditions):
    print("✅ 所有条件均满足")
else:
    print("❌ 至少一个条件未满足")  # 此处输出 ❌,因 'ef < 35' 为 False

关键优势与注意事项

  • 安全无 eval:完全规避代码注入风险,仅解析受信运算符与字面量;
  • 支持链式比较:0 < (cd) < 6 被正确拆解为 0 < (cd) 和 (cd) < 6 两次独立判断;
  • 类型智能推导:自动识别 12.5(float)、42(int)、"text"(str)、True/False、None;
  • ⚠️ 键名限制:字典键需为合法标识符或含括号/符号的字符串(如 '(cd)'),但不可含空格或运算符(如 'a b' 会解析失败);
  • ⚠️ 无数学表达式支持:不支持 a + b > 10 等算术运算,仅支持单键 + 运算符 + 字面量的原子条件;
  • ? 扩展建议:如需支持更复杂语法(如逻辑运算符 and/or、函数调用),推荐集成 pyparsing 或 lark 等专业解析器。

该方案在简洁性、安全性与实用性之间取得良好平衡,适用于配置驱动型校验、规则引擎轻量级实现等场景。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

531

2023.06.20

正则表达式不包含
正则表达式不包含

正则表达式,又称规则表达式,,是一种文本模式,包括普通字符和特殊字符,是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串,通常被用来检索、替换那些符合某个模式的文本。php中文网给大家带来了有关正则表达式的相关教程以及文章,希望对大家能有所帮助。

258

2023.07.05

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

767

2023.07.05

java正则表达式匹配字符串
java正则表达式匹配字符串

在Java中,我们可以使用正则表达式来匹配字符串。本专题为大家带来java正则表达式匹配字符串的相关内容,帮助大家解决问题。

219

2023.08.11

正则表达式空格
正则表达式空格

正则表达式空格可以用“s”来表示,它是一个特殊的元字符,用于匹配任意空白字符,包括空格、制表符、换行符等。本专题为大家提供正则表达式相关的文章、下载、课程内容,供大家免费下载体验。

357

2023.08.31

Python爬虫获取数据的方法
Python爬虫获取数据的方法

Python爬虫可以通过请求库发送HTTP请求、解析库解析HTML、正则表达式提取数据,或使用数据抓取框架来获取数据。更多关于Python爬虫相关知识。详情阅读本专题下面的文章。php中文网欢迎大家前来学习。

293

2023.11.13

正则表达式空格如何表示
正则表达式空格如何表示

正则表达式空格可以用“s”来表示,它是一个特殊的元字符,用于匹配任意空白字符,包括空格、制表符、换行符等。想了解更多正则表达式空格怎么表示的内容,可以访问下面的文章。

245

2023.11.17

正则表达式中如何匹配数字
正则表达式中如何匹配数字

正则表达式中可以通过匹配单个数字、匹配多个数字、匹配固定长度的数字、匹配整数和小数、匹配负数和匹配科学计数法表示的数字的方法匹配数字。更多关于正则表达式的相关知识详情请看本专题下面的文章。php中文网欢迎大家前来学习。

548

2023.12.06

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

69

2026.03.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.5万人学习

Django 教程
Django 教程

共28课时 | 5万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号