酸洗、压缩Python对象和存储在SQL中时丢失的信息

酸洗、压缩Python对象和存储在SQL中时丢失的信息,python,sql,scikit-learn,pickle,zlib,Python,Sql,Scikit Learn,Pickle,Zlib,我正在使用pickle和zlib库,使用pyodbc将3个对象序列化并压缩为nvarchar(MAX)存储在TSQL中。在另一端从SQL检索这些对象时,2成功地转换回它们的原始形式(2d numpy数组和sklearn.StandardScaler)。第三个对象(sklearn.gradientBoostingRegressionor)不会向后转换。下面是所用代码的摘要。还应该注意,我正在使用Pandas进行一些SQL工作 下面是酸洗、压缩和上载到SQL的代码: model_pickle = z

我正在使用pickle和zlib库,使用pyodbc将3个对象序列化并压缩为nvarchar(MAX)存储在TSQL中。在另一端从SQL检索这些对象时,2成功地转换回它们的原始形式(2d numpy数组和sklearn.StandardScaler)。第三个对象(sklearn.gradientBoostingRegressionor)不会向后转换。下面是所用代码的摘要。还应该注意,我正在使用Pandas进行一些SQL工作

下面是酸洗、压缩和上载到SQL的代码:

model_pickle = zlib.compress(pickle.dumps(est))
scaler_pickle = zlib.compress(pickle.dumps(scaler),1)
boundary_pickle = zlib.compress(pickle.dumps(bounds),1)

cnxn = pyodbc.connect('driver={SQL Server};server=XXX;database=XYZ;trusted_connection=true')
cursor = cnxn.cursor()

cursor.execute("""INSERT INTO AD_RLGNMNT_MDL_PICKLE (CHAIN_NUM,AD_LENGTH,GL_CODE,AD_TYPE,MODEL_PICKLE,SCALER_PICKLE,WFA_TEST,BOUNDS_PICKLE) VALUES (?,?,?,?,?,?,?,?);""",
               (chain_num.astype(np.int32),ad_length.astype(np.int32),gl_code.astype(np.int32),ad_type,model_pickle,scaler_pickle,WFA,boundary_pickle))
cursor.commit()
cursor.close()
cnxn.close()
下面是从SQL中提取、解压缩和取消勾选对象的代码:

model_pickle = pd.read_sql("""SELECT A.MODEL_PICKLE from AD_RLGNMNT_MDL_PICKLE A WHERE A.CHAIN_NUM = %s and A.ad_length = %s and A.GL_CODE = %s and A.AD_TYPE in ('%s');"""
            % (Current_chain_num, Current_ad_length, Current_GL, Current_ad_type),cnxn)
scaler_pickle = pd.read_sql("""SELECT A.SCALER_PICKLE from AD_RLGNMNT_MDL_PICKLE A WHERE A.CHAIN_NUM = %s and A.ad_length = %s and A.GL_CODE = %s and A.AD_TYPE in ('%s');"""
            % (Current_chain_num, Current_ad_length, Current_GL, Current_ad_type),cnxn)
bounds_pickle = pd.read_sql("""SELECT A.BOUNDS_PICKLE from AD_RLGNMNT_MDL_PICKLE A WHERE A.CHAIN_NUM = %s and A.ad_length = %s and A.GL_CODE = %s and A.AD_TYPE in ('%s');"""
            % (Current_chain_num, Current_ad_length, Current_GL, Current_ad_type),cnxn)

combos_list.set_value(i, 'model', model_pickle[['MODEL_PICKLE']].iloc[0].values[0])
combos_list.set_value(i, 'scaler', scaler_pickle[['SCALER_PICKLE']].iloc[0].values[0])
combos_list.set_value(i, 'bounds', bounds_pickle[['BOUNDS_PICKLE']].iloc[0].values[0])

model  = pickle.loads(zlib.decompress(model_pickle[['MODEL_PICKLE']].iloc[0].values[0]))
scaler = pickle.loads(zlib.decompress(scaler_pickle[['SCALER_PICKLE']].iloc[0].values[0]))
bounds = pickle.loads(zlib.decompress(bounds_pickle[['BOUNDS_PICKLE']].iloc[0].values[0]))
当我运行“model=pickle.loads”行时,我收到以下错误(最后两行工作正常):

错误:解压缩数据时出现错误-5:流不完整或被截断

我已经在SO和web上搜寻解决方案,并尝试了上述代码的无数变体。我比较了原始ASCI输入和输出,输入长度为203663个字符,而输出长度为203649个字符。输出在末尾缺少一个“\xB3”,中间有一个“XAA”和一个“\n”。p>
GradientBoostingRetressor对象有什么独特之处吗?把我的头发拔出来。

您需要使用二进制BLOB将数据存储在数据库中(实现起来更复杂)

在进行
base64
编码后,只需使用字符CLOB存储数据

import base64

model_pickle=base64.b64encode(zlib.compress(pickle.dumps(est)))

model=pickle.loads(zlib.decompress(base64.b64decode(model_pickle[['MODEL_PICKLE']].iloc[0].values[0])))

注意:增加数据量(+33%),但我认为这并不是很重要

您需要使用二进制BLOB将数据存储在数据库中(实现起来更复杂)

在进行
base64
编码后,只需使用字符CLOB存储数据

import base64

model_pickle=base64.b64encode(zlib.compress(pickle.dumps(est)))

model=pickle.loads(zlib.decompress(base64.b64decode(model_pickle[['MODEL_PICKLE']].iloc[0].values[0])))

注意:增加数据量(+33%),但我认为这不是非常重要的更新:这仅适用于一个示例。上面由用户缩进选择的答案修复了我的问题

明白了!将第一行代码修改为以下内容,其中包括选择最新的pickle协议

model_pickle = zlib.compress(pickle.dumps(est,protocol = 2))

**更新:这仅适用于一个示例。上面由用户缩进选择的答案修复了我的问题

明白了!将第一行代码修改为以下内容,其中包括选择最新的pickle协议

model_pickle = zlib.compress(pickle.dumps(est,protocol = 2))

不熟悉TSQL,但是二进制blob是不可能的吗?据我所知,nvarchar是一种unicode类型,使用可变长度编码。我不会用它来序列化二进制数据…不熟悉TSQL,但是二进制BLOB是不可能的吗?据我所知,nvarchar是一种unicode类型,使用可变长度编码。我不会用它来序列化二进制数据…太好了!使用字符CLOB(varchar(max))和base64编码。谢谢完美的使用字符CLOB(varchar(max))和base64编码。谢谢