苦练Python第37天:eval()函数的安全实践指南

266 阅读2分钟

前言

大家好,我是倔强青铜三。欢迎关注我,微信公众号:倔强青铜三。欢迎点赞、收藏、关注,一键三连!!!

欢迎来到 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(),可通过 globalslocals 限制作用域:

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_evaleval
用户输入JSON/asteval
复杂逻辑写函数eval 拼接字符串

✅ TL;DR 一句话总结

  • eval() 能跑,但别让它乱跑。
  • 对外输入 → 永远不用 eval()
  • 真要字面量 → ast.literal_eval() 真香。

最后感谢阅读!欢迎关注我,微信公众号倔强青铜三。欢迎点赞收藏关注,一键三连!!!