Python脚本读取DB中BLOB存储的CSV转DataFrame列名异常,Jupyter正常
问题描述
我有一张数据库表,包含8列:1列存储id,另外7列以BLOB二进制格式存储经过pickle序列化的CSV数据。读取这些数据并反序列化后,将每列数据存入单独的Pandas DataFrame中。
使用的代码如下:
engine = create_engine('sqlite:///test.db') metadata_obj = MetaData() metadata_obj.reflect(bind=engine) Tabla1 = Table('Tabla1', metadata_obj, autoload_with=engine) Session = sessionmaker(bind=engine) session = Session() query1= session.query(Tabla1).filter_by(idCliente=2).all() for i in query1: df1=pd.DataFrame(pickle.loads(i.df1)) df2=pd.DataFrame(pickle.loads(i.df2)) df3=pd.DataFrame(pickle.loads(i.df3)) df4=pd.DataFrame(pickle.loads(i.df4)) df5=pd.DataFrame(pickle.loads(i.df5)) df6=pd.DataFrame(pickle.loads(i.df6)) df7=pd.DataFrame(pickle.loads(i.df7)) df_list = [df1, df2, df3, df4, df5, df6, df7] df_names = ['df1', 'df2', 'df3', 'df4', 'df5', 'df6', 'df7'] df_dict = dict(zip(df_names, df_list)) print(df1.columns)
在Jupyter Notebook中执行这段代码时,能正确获取DataFrame的列名;但在CMD中通过python main.py执行脚本时,却将数据的第一行当作列名,无法得到正确结果。
已确认Jupyter Notebook和脚本的依赖版本完全一致:
pandas 2.1.0 sqlalchemy 2.0.21 python 3.9.13 pickle 4.0
解决方案
1. 确认序列化时的DataFrame完整性
问题核心大概率是序列化时没有完整保存DataFrame的列信息。Jupyter和脚本环境的隐性差异可能导致序列化的对象结构不同——比如在某些场景下,序列化的是DataFrame的底层数据(如二维列表)而非完整的DataFrame对象。
重新序列化数据时,直接保存完整的DataFrame对象:
import pickle import pandas as pd from sqlalchemy import create_engine, Table, MetaData # 读取原始CSV并转为DataFrame df = pd.read_csv('your_source.csv') # 序列化完整的DataFrame serialized_df = pickle.dumps(df) # 将序列化后的数据存入数据库 engine = create_engine('sqlite:///test.db') metadata_obj = MetaData() metadata_obj.reflect(bind=engine) Tabla1 = Table('Tabla1', metadata_obj, autoload_with=engine) with engine.connect() as conn: conn.execute(Tabla1.update().where(Tabla1.c.idCliente == 2).values(df1=serialized_df)) conn.commit()
2. 反序列化时强制指定列名
如果无法重新序列化数据,可从Jupyter中导出正确的列名列表,在脚本中手动指定:
# 从Jupyter中获取正确列名后填入 correct_columns = ['列名1', '列名2', '列名3'] # 替换为实际列名 for i in query1: # 反序列化后重置列名 df1_data = pickle.loads(i.df1) df1 = pd.DataFrame(df1_data, columns=correct_columns) # 其他df同理处理
3. 检查反序列化后的对象类型
在脚本中添加调试代码,确认反序列化后的对象类型:
loaded_data = pickle.loads(i.df1) print(f"反序列化对象类型: {type(loaded_data)}") print(f"数据前5行: {loaded_data[:5]}")
如果输出是二维列表/数组而非DataFrame,说明序列化时仅保存了数据,未保存列信息,必须重新序列化完整的DataFrame对象。
4. 统一工作目录
CMD执行脚本时的工作目录可能与Jupyter不同,导致隐性配置差异。在脚本开头添加工作目录检查与切换:
import os # 切换到Jupyter的工作目录(替换为实际路径) os.chdir("C:/your/jupyter/work/dir") print(f"当前工作目录: {os.getcwd()}")
内容的提问来源于stack exchange,提问作者user22826714
相关产品推荐
相关产品推荐

