前言
大家好,我是倔强青铜三。欢迎关注我,微信公众号:倔强青铜三。欢迎点赞、收藏、关注,一键三连!!!
欢迎来到 Python 百日冲刺第 37 天!
今天聊一把双刃剑——eval()。它能瞬间把字符串变成可执行代码,也能瞬间把服务器变成“矿机”。看完这篇,你会明白何时该用、何时该躲,以及如何用更安全的姿势“白嫖”动态求值。
🧠 eval() 是什么?
eval(expression) 把字符串当作 Python 表达式执行并返回结果:
result = eval("3 + 5")
print(result) # 8
看似魔法,实则风险拉满。
🚨 危险现场
一旦让外部用户控制输入,eval() 就可能执行任意代码:
user_input = "__import__('os').system('rm -rf /')"
eval(user_input) # 毁灭吧,系统!
哪怕一句 open('secret.txt').read() 也能泄露隐私。
✅ 何时才能用?
- 输入完全可信(如内部脚本、自动生成表达式)。
- 需求必须动态求值。
即使满足,也优先考虑更安全的替代方案。
🔐 安全替代方案
1️⃣ ast.literal_eval() —— 最推荐
只解析字面量:字符串、数字、列表、字典、布尔值、None。
import ast
expr = "{'name': 'Alice', 'age': 30}"
safe_result = ast.literal_eval(expr)
print(safe_result) # {'name': 'Alice', 'age': 30}
无法调用函数、无法导入模块,安全感直接拉满。
2️⃣ 用 JSON 做数据交换
结构化数据优先 JSON:
import json
data = json.loads('{"a": 10, "b": 20}')
跨语言、跨平台、零风险。
⚙️ 受限 eval():最后的倔强
若必须 eval(),可通过 globals 与 locals 限制作用域:
safe_globals = {"__builtins__": None}
safe_locals = {"x": 10, "y": 5}
expr = "x + y"
result = eval(expr, safe_globals, safe_locals)
print(result) # 15
缺点:绕过姿势千千万,依旧不推荐直接用于用户输入。
🛠️ 正当用例(仅限内部)
- 自研计算器 Demo(无网络、无用户输入)。
- 数据科学 Notebook 中完全可信的表达式。
- 受控沙箱里的内部工具。
🔄 速查表
| 场景 | 建议使用 | 千万别用 |
|---|---|---|
| 动态字面量 | ast.literal_eval | eval |
| 用户输入 | JSON/ast | 裸 eval |
| 复杂逻辑 | 写函数 | eval 拼接字符串 |
✅ TL;DR 一句话总结
eval()能跑,但别让它乱跑。- 对外输入 → 永远不用
eval()。 - 真要字面量 →
ast.literal_eval()真香。
最后感谢阅读!欢迎关注我,微信公众号:
倔强青铜三。欢迎点赞、收藏、关注,一键三连!!!