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

如何安全对包含列表索引的Python表达式进行求值?

报错原因

ast.literal_eval 仅支持解析Python原生字面量(数字、字符串、列表、字典、元组、布尔值、None等),不支持任何运算、索引、属性访问等操作,因此带有[1]索引操作的表达式会被判定为非法节点,抛出ValueError。

解决方案

方案1:自定义AST白名单解析(无依赖、最安全)

通过解析表达式为抽象语法树,仅放行你需要的「字面量构造+下标索引」类节点,完全禁止其他所有语法特性,不存在任意代码执行风险,适配Python全版本:

import ast

def safe_eval_literal_with_index(expr: str):
    # 定义允许的AST节点类型白名单
    allowed_nodes = (
        ast.Expression, ast.Module,
        ast.Constant, ast.NameConstant, # 字面量值兼容
        ast.List, ast.Tuple, ast.Dict, ast.Set, # 容器字面量
        ast.Subscript, ast.Index # 下标操作兼容
    )
    # 解析表达式为AST
    ast_tree = ast.parse(expr, mode="eval")
    # 遍历所有节点校验合法性
    for node in ast.walk(ast_tree):
        if not isinstance(node, allowed_nodes):
            raise ValueError(f"非法语法:不允许{type(node).__name__}操作")
    # 编译执行校验后的AST
    return eval(compile(ast_tree, filename="<safe_expr>", mode="eval"))

使用示例:

# 正常支持的场景
print(safe_eval_literal_with_index('[1, 2, 3][1]')) # 输出 2
print(safe_eval_literal_with_index('({"a":1, "b":2})["b"]')) # 输出 2
print(safe_eval_literal_with_index('(10, 20, 30)[-1]')) # 输出 30

# 危险操作会被拦截
safe_eval_literal_with_index('__import__("os").system("rm -rf /")') # 直接抛出ValueError

如果需要支持切片操作,只需要把ast.Slice添加到allowed_nodes白名单中即可。

方案2:第三方库simpleeval(功能更丰富)

如果需要支持更多简单操作(四则运算、属性访问、自定义函数白名单等),可以直接使用成熟的simpleeval库,它内部基于AST白名单实现,默认禁用所有危险操作:

  1. 安装依赖
pip install simpleeval
  1. 使用示例
from simpleeval import simple_eval

print(simple_eval('[1, 2, 3][1]')) # 输出 2

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 14:24:01