无法重新获取的Pickle文件打开报错UnpicklingError: pickle data was truncated求助
修复截断的Pickle文件以恢复部分DataFrame数据
问题背景
服务器上通过Pandas的to_pickle()方法备份了DataFrame对象,通过VSCode迁移到本地后,文件出现截断,打开时触发UnpicklingError: pickle data was truncated错误,且服务器已关闭无法重新生成或备份数据,需要尝试恢复部分数据。
原备份代码:
import pandas as pd congestion.to_pickle('/home/tugba/Emissions_Research/DATA2/congestion_sensitivity_short.pkl')
已尝试但失败的加载方式:
import pickle congestion = '/Users/aysetugbaozturk/Desktop/tugba/Emissions_Research/DATA2/congestion_sensitivity.pkl' with open(congestion, 'rb') as f: corpus = pickle.load(f) data_arr = pickle.loads(congestion) print(data_arr) congestion = pd.read_pickle('/Users/aysetugbaozturk/Desktop/tugba/Emissions_Research/DATA2/congestion_sensitivity.pkl')
可行恢复方法
方法1:增量读取捕获可用数据片段
Pickle是流式序列化格式,截断位置前的数据可能仍可读取。通过循环加载直到报错,提取未损坏的部分:
import pickle import pandas as pd file_path = '/Users/aysetugbaozturk/Desktop/tugba/Emissions_Research/DATA2/congestion_sensitivity.pkl' try: # 先尝试完整加载 with open(file_path, 'rb') as f: df = pickle.load(f) print("成功加载完整DataFrame") except pickle.UnpicklingError: # 增量读取,收集可用数据 with open(file_path, 'rb') as f: unpickler = pickle.Unpickler(f) recovered_items = [] while True: try: item = unpickler.load() recovered_items.append(item) except (EOFError, pickle.UnpicklingError): break # 尝试转为DataFrame(根据pickle结构调整) if recovered_items: try: df_recovered = pd.DataFrame(recovered_items[0]) print(f"恢复部分数据,共{len(df_recovered)}行") print(df_recovered.head()) except Exception as e: print(f"恢复原始数据片段:{recovered_items}")
方法2:用pickletools分析并截断文件到完整位置
利用pickletools解析pickle指令流,找到最后一个完整的指令位置,截断文件后尝试加载:
import pickletools import pickle import pandas as pd file_path = '/Users/aysetugbaozturk/Desktop/tugba/Emissions_Research/DATA2/congestion_sensitivity.pkl' # 第一步:解析pickle指令,找到完整数据的截断位置 with open(file_path, 'rb') as f: pickletools.dis(f) # 观察输出,找到最后一个完整的指令(比如最后一个STOP标记前的位置),记录字节数truncate_at # 第二步:截断文件到完整位置(示例值需替换为实际找到的字节数) truncate_at = 102400 # 替换为实际解析得到的完整位置 with open(file_path, 'rb+') as f: f.truncate(truncate_at) # 第三步:尝试加载修复后的文件 try: df = pd.read_pickle(file_path) print("修复后成功加载数据") except Exception as e: print(f"修复后加载失败:{e}")
方法3:指定不同Pickle协议版本加载
不同Python版本的Pickle协议可能存在兼容问题,尝试指定协议版本加载:
import pickle import pandas as pd file_path = '/Users/aysetugbaozturk/Desktop/tugba/Emissions_Research/DATA2/congestion_sensitivity.pkl' with open(file_path, 'rb') as f: # 尝试所有可用协议版本(0到5) for protocol in range(6): try: f.seek(0) df = pickle.load(f, fix_imports=True, encoding='utf-8', errors='replace', protocol=protocol) print(f"使用协议{protocol}成功加载数据") break except Exception as e: print(f"协议{protocol}加载失败:{e}")
注意事项
- 以上方法无法保证恢复全部数据,但大概率能提取部分可用内容
- 若恢复的是DataFrame片段,可能需要手动调整结构以正常使用
- 后续迁移文件时建议校验文件哈希值(如MD5),确认传输完整性
内容的提问来源于stack exchange,提问作者Ayse Tugba Ozturk
相关产品推荐
相关产品推荐

