2013-12-17 27 views
4

當我使用泡菜時,它工作正常,我可以轉儲任何負載。泡菜轉儲替換當前文件數據

問題是如果我關閉程序並嘗試再次轉儲,它將用新轉儲替換舊文件數據。這裏是我的代碼:

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() 

回答

0

打開文件"wb"模式截斷文件 - 也就是說,它會刪除文件的內容,然後讓你進行這項工作。

通常情況下,你會打開文件追加("ab")模式在最後添加數據。但是,Pickle不支持追加,因此您必須將數據保存到一個新文件(使用不同的文件名 - 詢問用戶或使用命令行參數,如-o test.txt?),每次程序運行。

關於相關主題,請勿使用Pickle。這是不安全的。考慮使用JSON代替(它在標準庫 - import json)。

+0

答案的前半部分是正確的......但下半部分不是。 Pickle確實支持添加。至於「不安全」,如果你試圖保存除float/str/list/dict之外的類型,JSON不能這樣做,除非你擴展它,在這種情況下,它變得和pickle一樣不安全。你必須知道你的數據以及你想如何存儲它,或者沒有一般的安全答案。 – abarnert

+0

編號Pickle本質上是危險的(因爲模塊的文檔需要多次注意警告),'pickle.load' *將執行包含在pickled文件中的任意代碼*:http://michael-rushanan.blogspot .ca/2012/10/why-python-pickle-is-insecure.html –

+0

如果你甚至沒有試圖理解爲什麼pickle是危險的,你最終會寫代碼,這些代碼只是使用擴展JSON或其他方式。警告中特別提到的是「醃泡模塊不能防止錯誤或惡意構建的數據。」如果您以顯而易見的方式擴展JSON以存儲和恢復自定義類,那麼對於錯誤或惡意構造的數據而言,它將同樣不安全。 – abarnert

7

當你用w模式(或wb)打開一個文件時,它告訴它寫一個全新的文件,擦除已經存在的文件。

由於the docs說:

的模式最常用的值是「R」的閱讀,「W」寫(截斷文件,如果它已經存在),和「A」對於追加...

換句話說,你想用'ab',不'wb'


但是,當您將新轉儲追加到同一文件時,最終會生成由多個單獨值組成的文件。如果您只撥打load一次,它只會加載第一個。如果你想加載所有的,你需要編寫這樣的代碼。例如,您可以將load循環到EOFError


真的,它看起來就像你正在試圖做的是不追加到泡菜文件,但修改現有醃字典。

你可以做到這一點與加載和合並所有堆放在一起,這樣的功能:

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 

但是,這會越來越慢,你運行你的程序的次數越多,因爲你堆越來越多的相同值的副本。要做到這一點你需要加載舊的字典,修改它,然後轉儲修改後的版本。爲此,你想要w模式。

但是,至少如果密鑰是字符串,更好的方法是使用dbm(如果值也是字符串)或shelve(否則),而不是字典放在第一位。