必须换掉eval的场景是处理来自用户输入、网络请求、配置文件等不可信来源的字符串时,因其可执行任意代码造成安全风险;ast.literal_eval仅解析python字面量,天然防注入,是安全替代方案。

直接用 ast.literal_eval 替代 eval,绝大多数字符串转结构化数据的场景都能安全解决。
哪些情况必须换掉 eval
当你处理的字符串来自用户输入、网络请求、配置文件或任何不可信来源时,eval 就不该出现。它能执行任意代码,比如 "__import__('os').system('rm -rf /')" 这类输入会直接危害系统。哪怕只是做计算器,也建议不用 eval —— 它本就不是为这类任务设计的。
ast.literal_eval 是最常用的安全替代
它只允许解析 Python 字面量:数字、字符串、列表、字典、元组、集合、True/False 和 None。其他任何内容(函数调用、变量名、表达式)都会报 SyntaxError,天然防注入。
- 转换列表:
ast.literal_eval("[1, 2, 'hello']") - 转换字典:
ast.literal_eval("{'name': 'Alice', 'age': 30}") - 转换嵌套结构:
ast.literal_eval("{'data': [1, {'x': 2}]}"
注意:它不支持 JSON 风格的 true、false、null,如果原始数据是标准 JSON 字符串,优先用 json.loads()。
其他常见场景的对应方案
不同需求有更贴切的工具:
-
解析 JSON 字符串 → 用
json.loads(),专为 JSON 设计,类型严格,性能好 -
安全计算简单表达式 → 用第三方库如
simpleeval或手动实现四则运算解析器 -
动态加载模块或配置 → 改用
importlib、YAML/INI 解析器,或定义明确的配置结构 -
需要真正动态执行逻辑 → 极少数情况(如 REPL、插件系统),应严格沙箱隔离,而非依赖
eval的“简易”假象
识别和清理已有 eval 调用
项目中已有 eval 时,先定位风险点:
- 检查参数是否来自
input()、request.form、open().read()等外部源 - 若参数是固定字符串或完全可控的内部拼接,风险较低,但仍建议替换以统一规范
- 可用
ast模块写个简单扫描脚本,自动发现所有eval(…)调用并标记上下文
替换后务必测试原功能是否正常,尤其注意类型差异——literal_eval 返回的是确切的 Python 对象,不会意外触发方法或副作用。











