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

How to unpickle objects from .pkl file using python

我创建了一个学生 class.I 将每个学生的详细信息存储在 file.I 使用序列化概念来存储 details.The 问题是在解开它给第一个对象的数据时 only.Can 有人说如何检索 .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)

您遇到的问题是 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 整个列表并在对 pickle.dump 的一次调用中将其全部写出,覆盖数据文件的先前内容。不是在用户请求时读取数据,而是在程序开始时读取它,如果用户稍后需要它,它已经在内存中。

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

就在学生 class 的定义下方:

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 实例(也许您正在记录实验室合作伙伴或某些团队),则此方法也比其他版本好得多小组项目)。如果您单独 pickle 此类相互连接的对象,则当您再次加载它们时,它们之间的链接将不会保留。加载的版本仍将有引用,但引用将指向其他 Student 实例的副本,而不是您在其他 Student 自行加载时获得的副本。但是,如果您一次转储并加载整个 Student 列表,它们的互连将保持不变。 (这是相当深的东西,如果你不明白我在说什么,不要太担心。)