You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python校验字符串类型的数学表达式是否合法

Python 校验仅含数字的合法数学表达式方案

完全可以用Python现有库实现,无需自行开发完整的词法、语法校验逻辑,以下是两种成熟的实现方式:


方法1:使用内置ast模块(推荐,无需安装第三方依赖)

ast是Python标准库自带的抽象语法树模块,仅解析表达式不执行代码,安全性高,完全适配需求。

实现代码

import ast
import operator

# 可按需扩展允许的运算符,比如支持乘方可加ast.Pow
ALLOWED_OPERATORS = {
    ast.Add: operator.add,
    ast.Sub: operator.sub,
    ast.Mult: operator.mul,
    ast.Div: operator.truediv,
    ast.USub: operator.neg  # 支持负号写法,比如-2
}

def is_valid_num_expression(exp: str) -> bool:
    # 第一步校验语法合法性,括号不匹配、表达式不完整直接报错
    try:
        tree = ast.parse(exp, mode='eval')
    except SyntaxError:
        return False

    # 第二步校验仅含数字和允许的运算符,无字母、变量等非法内容
    def _check_node(node):
        if isinstance(node, ast.Expression):
            return _check_node(node.body)
        elif isinstance(node, ast.BinOp):
            # 二元运算,校验运算符和左右操作数
            return type(node.op) in ALLOWED_OPERATORS and _check_node(node.left) and _check_node(node.right)
        elif isinstance(node, ast.UnaryOp):
            # 一元运算,校验运算符和操作数
            return type(node.op) in ALLOWED_OPERATORS and _check_node(node.operand)
        elif isinstance(node, ast.Constant):
            # 常量必须为数字类型,Python3.8以下版本替换为ast.Num判断即可
            return isinstance(node.value, (int, float))
        else:
            # 遇到变量、函数调用等其他节点直接返回不合法
            return False

    return _check_node(tree)

测试效果

print(is_valid_num_expression("(5+5)-(5)+(-2)")) # True
print(is_valid_num_expression("(5+5)/2-1")) # True
print(is_valid_num_expression("(5+5)/(3-1)")) # True
print(is_valid_num_expression("(5+5)/(3-1")) # False
print(is_valid_num_expression("5+")) # False
print(is_valid_num_expression("(5+5)/()")) # False
print(is_valid_num_expression("(a+b)/5")) # False

方法2:使用第三方sympy库(适合后续需要计算表达式值的场景)

如果需求除了校验之外还要对合法表达式做计算,可以用sympy的表达式解析能力,只需额外执行pip install sympy安装即可。

实现代码

from sympy import parse_expr

def is_valid_num_expression_sympy(exp: str) -> bool:
    try:
        # 传入空的变量字典,遇到字母、变量会直接抛出异常
        expr_obj = parse_expr(exp, local_dict={})
        # 二次校验没有未定义的符号变量
        return len(expr_obj.free_symbols) == 0
    except:
        return False

校验通过后直接调用expr_obj.evalf()就能得到表达式的计算结果。


注意:不要直接用eval()做校验,存在恶意代码执行风险,以上两种方案都是仅解析不执行,安全性有保障。

内容的提问来源于stack exchange,提问作者PaulRuban

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 01:54:03