如何加载存储在SQL表行中的pickle序列化对象?
问题描述
我在加载存储在SQL表中的pickle序列化对象时遇到问题。表结构如下:
| ModelId | ModelObject |
|---|---|
| 1 | 0x800363736B6C6561726E2E6C696E6561725F6D6F64656C2E636F6F7264696E6ACAEE3FABCEEFD58889F13F3C19DFC8235DF03F3E6FDAB870B5F43F1C31AB7E93BEF23F5F5223C65948EF3FD08961D |
| 2 | 0x800845242158652135486524156ER... |
ModelObject列的字符串是通过pickle.dumps生成的pickle序列化数据。尝试加载第一个模型对象时失败,使用的代码如下:
conn = pyodbc.connect('Driver={SQL Server};' 'Server=MyServer;' 'Database=MyDatabase;' 'Trusted_Connection=yes;') sql_query = "SELECT * FROM [MyDatabase].[dbo].[models_data]" tbl = pd.read_sql(sql_query, conn) model_1 = pd.read_pickle(tbl.iloc[0]['ModelObject']) model_1 = pickle.load(tbl.iloc[0]['ModelObject'])
报错信息:
pd.read_pickle抛出:AttributeError: 'bytes' object has no attribute 'seek'pickle.load抛出:TypeError: file must have 'read' and 'readline' attributes
解决方法
问题核心在于SQL存储的是十六进制字符串格式的pickle数据,且pickle.load/pd.read_pickle的参数使用错误,按以下步骤修复:
转换十六进制字符串为原始bytes数据
SQL表中ModelObject的内容是带0x前缀的十六进制字符串,需要先移除前缀,再转换为pickle原始bytes:hex_str = tbl.iloc[0]['ModelObject'] pickle_bytes = bytes.fromhex(hex_str[2:])使用
pickle.loads加载内存中的bytes数据pickle.load要求传入文件对象,而pickle.loads直接支持bytes类型的输入,这才是加载内存中pickle数据的正确方式:import pickle model_1 = pickle.loads(pickle_bytes)完整可运行代码
整合后的完整流程代码:import pyodbc import pandas as pd import pickle conn = pyodbc.connect('Driver={SQL Server};' 'Server=MyServer;' 'Database=MyDatabase;' 'Trusted_Connection=yes;') sql_query = "SELECT * FROM [MyDatabase].[dbo].[models_data]" tbl = pd.read_sql(sql_query, conn) # 加载第一个模型对象 hex_str = tbl.iloc[0]['ModelObject'] pickle_bytes = bytes.fromhex(hex_str[2:]) model_1 = pickle.loads(pickle_bytes)
内容的提问来源于stack exchange,提问作者userpisquared
相关产品推荐
相关产品推荐

