2011-07-28 60 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