编程后端开发者

解释一下Python中内置的数据序列化机制是如何工作的(模块pickle和json)。它们有什么不同,用途是什么,不谨慎的序列化会带来哪些危险?

用 Hintsage AI 助手通过面试

回答

在Python中,用于序列化(将对象转换为字节序列或字符串以进行存储/传输)的模块是picklejson

  • pickle可以序列化任何Python对象(甚至类和函数!),但结果是二进制序列。该模块仅在Python生态系统内部工作。
  • json只能序列化简单的数据结构(dict、list、str、int、float),但结果将是一个字符串(通用格式),与其他语言兼容。

在存储/传输数据时使用pickle与不受信方之间的交换是危险的,因为在反序列化时可能会执行任意恶意代码。json不存在这个缺点。

示例代码:

import pickle import json # Pickle(二进制序列化) data = {'x': 10, 'func': lambda x: x + 1} with open('data.pkl', 'wb') as f: pickle.dump(data, f) # JSON(仅简单对象) data = {'x': 10, 'y': [1, 2, 3]} with open('data.json', 'w') as f: json.dump(data, f)

反问问题

问题: 可以使用pickle在不同会话之间序列化和保存任何Python对象吗?为什么不推荐使用该机制来保存用户数据?

回答:

不,随处使用pickle是不明智的实践。除了安全性(加载“外部”pickled对象时执行可能被危害),还有Python或类版本不匹配的问题——如果类的结构发生变化,序列化对象可能无法加载或表现不正常。

示例:

# 加载pickle文件,类的结构已发生变化 import pickle with open('old_version.pkl', 'rb') as f: obj = pickle.load(f) # AttributeError或结构不匹配

历史

示例 1

在一个大型项目中为存储用户档案使用了pickle。在更新Python版本和更改类后,序列化对象的结构失去了兼容性,导致系统故障和大多数用户数据的丢失。


示例 2

在一个Web服务中,pickle用于用户会话。恶意用户加载了恶意的pickled对象,导致服务器上执行代码注入。


示例 3

尝试通过pickle序列化函数并通过网络传输失败,在某些环境中:pickled lambda无法在不同配置/版本的计算机之间移动。