Python r+模式下使用Pickle写入后无法读取内容的问题
问题:Pickle在r+b模式下读写文件失效的原因与解决办法
我想用Pickle从文件读取列表,更新后再写回同一文件,但用r+b模式操作后读不到更新后的内容。用的是Windows 10系统,试过网上说的f.seek(f.tell())解决方案,但对Pickle写入没用。
测试代码(失效情况):
import pickle with open("data.bin", "r+b") as file: temp_data = pickle.load(file) temp_data.append("test") file.seek(file.tell()) pickle.dump(temp_data, file) with open("data.bin", "rb") as file: print(pickle.load(file)) # 输出空列表
分开读写就能正常工作:
import pickle temp_data = [] with open("data.bin", "rb") as file: temp_data = pickle.load(file) with open("data.bin", "wb") as file: temp_data.append("test") pickle.dump(temp_data, file) with open("data.bin", "rb") as file: print(pickle.load(file)) # 输出 ['test']
想知道问题原因,以及是否必须分开读写?
问题原因
- 文件指针与内容追加问题:用
r+b模式读取完数据后,文件指针停在文件末尾。file.seek(file.tell())等于没移动指针,此时写入是在原内容后面追加新的序列化数据。当你再次读取时,Pickle会加载文件中第一个序列化对象(也就是原来的空列表),自然看不到更新后的内容。 - Windows文件机制限制:Windows下
r+b模式的文件缓存和锁定逻辑,会导致追加的新内容无法覆盖旧数据,进一步加剧了这个问题。你试的seek(f.tell())通常是解决文本文件的换行符缓存问题,对Pickle的二进制序列化场景不适用。
解决办法
不是必须分开读写,但分开读写是最省心可靠的方式。如果一定要用单文件句柄完成操作,可以这样改:
import pickle with open("data.bin", "r+b") as file: temp_data = pickle.load(file) temp_data.append("test") # 把指针移回文件开头 file.seek(0) # 截断文件,删除原内容后续部分 file.truncate() pickle.dump(temp_data, file) with open("data.bin", "rb") as file: print(pickle.load(file)) # 输出 ['test']
这个方法先把指针移到开头,再截断文件清空原有内容,最后写入新数据,相当于模拟了wb模式的覆盖效果,同时保留了单句柄操作的场景。
内容的提问来源于stack exchange,提问作者MitchelK
相关产品推荐
相关产品推荐

