如何使用python从.pkl文件中取消对象

时间:2015-04-21 05:52:13

标签: python pickle

我创建了一个学生班。我将每个学生的详细信息存储在一个文件中。我使用序列化概念来存储细节。问题是在取消数据时它只给出了第一个对象。任何人都可以说如何检索所有的对象在.pkl文件中

我的代码是

这是我的代码

'''
Created on Apr 20, 2015

@author: murali

'''
import pickle
from pip._vendor.distlib.compat import raw_input
class Student:
    def __init__(self, name, roll, sex, subject, total):
        """Return a new Car object."""
        self.name = name
        self.roll = roll
        self.sex = sex
        self.subject = subject
        self.total = total

print ("*************MENU*******************************")
print ("\t 1.Add New Student")
print ("\t 2.Display all Students")
print ("\t 3.Delete Student")
print ("\t 4.Display all Boys")
print ("\t 5.Display all Girls")
print ("\t 6.Display ascending order of marks")
print ("\t 7.Display alphabetical order of names ")
print ("\t 0.exit")
print ("************************************************")

print ("\n Enter your choice")
ch=int(raw_input())

if ch==1:
    print ("Enter Student Details")     
    print ("Enter Student Name")  
    n=raw_input()
    print ("Enter Student Roll number") 
    r=raw_input()
    print ("Male or Female")
    s=raw_input()
    print ("Enter Subject ")
    su=raw_input()
    print ("Enter Student marks ")
    t=raw_input()
    s=Student(n,r,s,su,t);
    with open("save2.pkl",'ab') as outfile:
        pickle.dump(s,outfile)
        print ("Data saved Successfully")
elif ch==2:
    st=[];
    f=open("save2.pkl",'rb')
    storedlist=pickle.load(f)
    print (storedlist)
    #st.append(storedlist)
    print ("Students are-")
    print (storedlist)
    #for i in storedlist:
    print(storedlist.name)
    print(storedlist.roll)
    print(storedlist.sex)
    print(storedlist.subject)
    print(storedlist.total)
    f.close();
    #s1=None
    #with open("save2.pkl",'rb') as infile:
        #s1=pickle.load(infile)
        #print (s1.name)
        #print (s1.roll)
        #print (s1.sex)
        #print (s1.subject)

1 个答案:

答案 0 :(得分:0)

您遇到的问题是pickle.load只会从您的pkl文件中读取一个项目。这就是它的设计方式。如果您在同一个文件中有多个项目,那么您需要重复加载它们,直到获得EOFError时无法阅读。类似的东西:

students = []
try:
    with open("save2.pkl",'rb') as f:
        while True:                          # loop indefinitely
            students.append(pickle.load(f))  # add each item from the file to a list
except EOFError:                             # the exception is used to break the loop
    pass                                     # we don't need to do anything special

或者,您可以在内存中保留文件要包含的项目的完整列表(例如,所有Student个实例)。修改列表后,您可以通过一次调用pickle.dump来整理整个列表并将其全部写出来,覆盖您数据文件的先前内容。不是在用户请求时读取数据,而是在程序开始时读取数据,如果用户以后需要,则已将其存储在内存中。

这有点难以展示,因为我不想重写代码的大块。我认为这些片段就是您所需要的:

正好在学生班的定义之下:

try:
    with open("save2.pkl",'rb') as f:
        students = pickle.load(f)     # just one call, loads the whole list
except FileNotFoundError:             # if the file doesn't exist, make an empty list
    students = []

您当前正在追加该文件的位置:

s=Student(n,r,s,su,t)
students.append(s)                        # update the in-memory list of students
with open("save2.pkl",'wb') as outfile:   # use mode "w" to overwrite existing file
    pickle.dump(students, outfile)        # dump the whole list, not only s
    print ("Data saved Successfully")

在后面的代码中,您不需要重新读取该文件。它可以只使用你已经在内存中的students列表。

鉴于您目前的菜单设计只能通过一次,第二种方法并不十分有用。但是如果你以后把菜单放在一个循环中(因为0选项建议你最终会想要这样做),你可能会喜欢不需要一遍又一遍地读取数据文件。

如果您将Student类型扩展为引用其他Student个实例(或许您正在记录实验室合作伙伴或某些团队,那么这种方法也比其他版本好得多)小组项目)。如果单独挑选这些互连对象,则再次加载它们时,它们之间的链接将不会保留。加载的版本仍将具有引用,但引用将是其他Student实例的副本,而不是与其他Student自身加载时相同的副本。但是,如果同时转储并加载整个Student列表,则会保留它们的互连。 (这是相当深刻的东西,如果你不理解我所说的话,不要太担心。)