在Python中,用于序列化(将对象转换为字节序列或字符串以进行存储/传输)的模块是pickle和json:
在存储/传输数据时使用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或结构不匹配
历史
在一个大型项目中为存储用户档案使用了pickle。在更新Python版本和更改类后,序列化对象的结构失去了兼容性,导致系统故障和大多数用户数据的丢失。
在一个Web服务中,pickle用于用户会话。恶意用户加载了恶意的pickled对象,导致服务器上执行代码注入。
尝试通过pickle序列化函数并通过网络传输失败,在某些环境中:pickled lambda无法在不同配置/版本的计算机之间移动。