2011-07-28 101 views
1

我正在使用cPickle來存儲對象。稍後我想修改個人記錄。不幸的是,文件得到修改後損壞(我得到UnpicklingError):Python:修改醃漬對象

創建和泡菜

class Book(object): 
    def __init__(self, title, author, ISBN, price): 
     self.title = title 
     self.author = author 
     self.ISBN = ISBN 
     self.price = price 

def main(): 
    from cPickle import dump 
    from random import choice 
    from random import randrange 
    letters = ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", 
      "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", 
      "w", "x", "y", "z") 
    f = open("books.dat", "a+b") 

    for ctr in range(0, 20): 
     title = "" 
     author = "" 
     ISBN = "" 
     price = randrange(20,100) 
     for i in range(10): 
      title+=choice(letters) 
      author+=choice(letters) 
      ISBN+=str(randrange(0,14)) 
     book = Book(title, author, ISBN, price) 
     # writing structure 
     dump(book, f) 
    f.close() 
    print "Finished." 

main() 

unPickle和修改

class Book(object): 
    def __init__(self, title, author, ISBN, price): 
     self.title = title 
     self.author = author 
     self.ISBN = ISBN 
     self.price = price 

    def __str__(self): 
     rep = self.title+" by "+self.author+".\n" 
     rep += "ISBN: "+self.ISBN+"\n" 
     rep += "Price: "+str(self.price) 
     return rep 

def main(): 
    from cPickle import load 
    from cPickle import dump 
    import sys 

    books = [] 
    EOF = False 
    f = open("books.dat", "r+b") 
    print "Loading..." 
    while not EOF: 
     try: 
      book = load(f) 
     except(EOFError): 
      EOF = True 
     else: 
      books.append(book) 
    print "Load complete." 
    rec = int(raw_input("Record to delete: ")) 
    print books[rec] 
    fwd = 0 
    for i in range(rec): 
     fwd+= sys.getsizeof(books[i]) 
    print str(fwd) 
    title = "New" 
    author = "New" 
    ISBN = "New" 
    price = 0 
    new = Book(title, author, ISBN, price) 
    print str(sys.getsizeof(new)) 
    f.seek(fwd) 
    dump(new, f) 
    f.close() 

main() 
+0

什麼是確切的錯誤?無論如何,你可以嘗試使用現在內置的sqlite3模塊。如果您必須這樣做,那麼這也將提供一個更容易遷移到真實數據庫的途徑。 – Keith

+0

回溯(最近通話最後一個): 文件 「/Users/aed0101/Dropbox/QSAP/cPickle/unpack.py」 49行,在 的main() 文件「/用戶/ aed0101/Dropbox的/ QSAP/cPickle的/unpack.py「,第27行,主要爲 book = load(f) UnpicklingError:無效加載密鑰'_'。 – aeed0101

+0

我已經試過sqlite3。將使用它。謝謝! – aeed0101

回答

2

我不知道,但在我看來,既然你已經有了一個書目對象列表(從文件加載),所以如果你將用這個列表的上下文重寫你的文件,你會更容易和無錯誤的(你可以刪除你想要的記錄或簡單的書[i] = new )使用轉儲而不是試圖找到一個t的地方o插入你的新紀錄。

換句話說嘗試以下操作:

class Book(object): 

    def __init__(self, title, author, ISBN, price): 
     self.title = title 
     self.author = author 
     self.ISBN = ISBN 
     self.price = price 

    def __str__(self): 
     rep = self.title+" by "+self.author+".\n" 
     rep += "ISBN: "+self.ISBN+"\n" 
     rep += "Price: "+str(self.price) 
     return rep 

def main(): 
    from cPickle import load, dump 

    print "Loading..." 
    books = [load(line) for line in open("books.dat", "rb")] 
    print "Load complete." 

    rec = int(raw_input("Record to delete: "))   
    title = "New" 
    author = "New" 
    ISBN = "New" 
    price = 0 

    books[rec] = Book(title, author, ISBN, price) # replace previous record 

    with open("books.dat", "wb") as f:   
     for record in books: 
      dump(record, f) 


main() 
+0

謝謝。我試圖在不覆蓋的情況下做到這一點。似乎getsizeof沒有報告正確的大小。 – aeed0101

+0

@ aeed0101 - 不確定在這種情況下使用seek,getsizeof等會給您帶來好處。 –

+0

假設書len是零? – gath