Skip to main content
Documents
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

Eval 函数

下面是一份 《Python eval() 最佳实践 + 安全风险 + 替代方案完整版指南》

内容涵盖:eval 是什么、能做什么、为什么危险、正确安全替代方案、实际项目中的最佳写法。

✅ 1. eval 是什么?

eval(expr) 会把 字符串转成 Python 表达式并执行,并返回表达式的“值”。

示例:

eval("1 + 2")        # 3
eval("'a' * 3")      # 'aaa'
eval("{'x': 1}")     # {'x': 1}

它会:

  • 解析字符串
  • 当成 Python 代码执行
  • 返回执行结果

⚠️ eval 与 exec 的区别:

函数 用途
eval() 执行表达式,有返回值
exec() 执行一段代码块,无返回值

❌ 2. eval 的巨大安全风险(必须了解)

如果字符串不是你自己完全控制,例如来自:

  • 用户输入
  • 数据库内容
  • HTTP 请求参数
  • 外部文件

那么运行 eval 会等于:

👉 给用户一把可以远程执行你服务器上任意 Python 代码的刀

例如:

eval("__import__('os').system('rm -rf /')")

这可以直接破坏服务器文件系统。

⚠️ 只要你不是在自己控制的代码里,eval 永远不能直接用。

⚠️ 3. 哪些场景不要使用 eval?

以下全都不允许 eval:

  • ❌ 字典转为对象
  • ❌ 将字符串解析为 list/dict
  • ❌ 配置文件解析
  • ❌ SQL 解析
  • ❌ JSON 解析
  • ❌ 数学表达式计算
  • ❌ 格式化模板

✅ 4. eval 的安全替代方案(最常用)

4.1 字符串 -> dict / list

❌ 不要用:

eval("{'a': 1}")

✅ 安全:

import ast
data = ast.literal_eval("{'a': 1}")

literal_eval 只允许字面量(字符串、数字、列表、字典等),安全无害。

4.2 解析 JSON

import json
json.loads('{"a": 1}')

4.3 执行数学表达式

安全库:

pip install simpleeval
from simpleeval import simple_eval
simple_eval("1 + 2 * 3")

4.4 运行受限环境下的 eval

如果必须使用 eval(极少数情况),请加上 限制变量环境:

safe = eval("1 + 2", {"__builtins__": None}, {})

✅ 5. eval 的正确用法(极少数情况)

只有你 完全信任表达式内容来源 时可以用 eval。

例如:

  • 在你写的配置脚本里
  • 在内部工具脚本中
  • 在 REPL 构建动态表达式

示例:

expr = "a + b"
result = eval(expr, {}, {"a": 1, "b": 2})

这代表:

  • 不允许使用 Python 内置函数
  • 仅允许使用 a 和 b
  • 无法执行危险代码

✅ 6. eval 的典型使用示例(安全环境中)

动态运行简单表达式

allowed = {"x": 10, "y": 20}
expr = "x * y + 5"
result = eval(expr, {"__builtins__": None}, allowed)

动态选择函数

actions = {
    "sum": lambda x, y: x + y,
    "mul": lambda x, y: x * y,
}

func_name = "sum"
expr = f"actions['{func_name}'](3, 5)"

result = eval(expr, {"actions": actions})

🚫 7. 项目中禁止 eval 的原因(生产环境经验)

在真实项目中,99% 的 eval 使用场景都可以用安全方法替换:

需求 替代方案
字符串转 dict ast.literal_eval
解析 JSON json.loads
构造表达式 字典映射 + if/dispatch
配置文件 json / yaml / toml
数学表达式 simpleeval
动态函数 映射表 + getattr

🎯 8. 总结(记住三句话)

  • eval 会执行任意 Python 代码,本质上是不安全的。
  • 绝不要在不可信数据上使用 eval。
  • 使用 ast.literal_eval 或 json.loads 代替。