Pickle转储替换当前文件数据

时间:2013-12-17 02:10:07

标签: python pickle

当我使用泡菜时,它工作正常,我可以倾倒任何负载。

问题是如果我关闭程序并尝试再次转储,它会用新转储替换旧文件数据。这是我的代码:

import pickle
import os
import time


dictionary = dict()


def read():
    with open('test.txt', 'rb') as f:
        a = pickle.load(f)
    print(a)
    time.sleep(2)


def dump():
    chs = raw_input('name and number')
    n = chs.split()
    dictionary[n[0]] = n[1]
    with open('test.txt', 'wb') as f:
        pickle.dump(dictionary, f)


Inpt = raw_input('Option : ')
if Inpt == 'read':
    read()
else:
    dump()

2 个答案:

答案 0 :(得分:8)

当您以w模式(或wb)打开文件时,它会告诉它写一个全新的文件,删除已有的文件。

正如the docs所说:

  

最常用的模式值是'r'用于阅读,'w'用于书写(截断文件,如果文件已经存在),'a'用于追加...

换句话说,您希望使用'ab',而不是'wb'


但是,当您将新转储附加到同一文件时,最终会得到一个由多个单独值组成的文件。如果你只调用load一次,它就会加载第一个。如果要加载所有,则需要编写执行此操作的代码。例如,您可以在load之前循环EOFError


真的,看起来你要做的不是附加到pickle文件,而是修改 现有的 pickle字典。

您可以使用将所有转储加载和合并在一起的函数来执行此操作,如下所示:

def Load():
    d = {}
    with open('test.txt', 'rb') as f:
        while True:
            try:
                a = pickle.load(f)
            except EOFError:
                break
            else:
                d.update(a)
    # do stuff with d

但是,当您运行程序的次数越来越多时,这将越来越慢,因为您会堆积越来越多的相同值的副本。要执行 right ,您需要加载旧字典,修改它,然后转储修改后的版本。为此,您想要 w模式。

然而,一个更好的方法来保持字典,至少如果键是字符串,是使用dbm(如果值也是字符串)或shelve(否则)而不是字典首先。

答案 1 :(得分:0)

"wb"模式打开文件会截断文件 - 也就是说,它会删除文件的内容,然后允许您对其进行处理。

通常,您将以附加("ab")模式打开文件,以便在结尾添加数据。但是,Pickle不支持附加,因此您必须将数据保存到新文件(提供不同的文件名 - 询问用户或使用命令行参数,例如-o test.txt? )每次运行程序。

在相关主题上,请勿使用Pickle。这是不安全的。请考虑使用JSON(它位于标准库中 - import json)。