从文件中保存和加载类实例

时间:2017-04-12 14:28:10

标签: python python-2.7

我的项目的一个重要部分是能够将类实例保存并加载到文件中。对于进一步的上下文,我的类既有一组属性,也有一些方法。

到目前为止,我已尝试使用 pickle ,但它的工作效果并不如预期。对于初学者来说,它没有加载方法,也没有让我添加我最初定义的属性;换句话说,它并没有真正复制我可以使用的课程。

相关守则:

class Brick(object):

    def __init__(self, name, filename=None, areaMin=None, areaMax=None, kp=None): 
        self.name = name
        self.filename = filename
        self.areaMin = areaMin
        self.areaMax = areaMax
        self.kp = kp
        self.__kpsave = None
        if filename != None:
            self.__logfile = file(filename, 'w')
    def __getstate__(self):
        f = self.__logfile
        self.__kpsave = []
        for point in self.kp: 
            temp = (point.pt, point.size, point.angle, point.response, point.octave, point.class_id)
            self.__kpsave.append(temp)
        return (self.name, self.areaMin, self.areaMax, self.__kpsave,
                f.name, f.tell())
    def __setstate__(self, state):
        self.value, self.areaMin, self.areaMax, self.__kpsave, name, position = state
        f = file(name, 'w')
        f.seek(position)
        self.__logfile = f
        self.filename = name
        self.kp = [] 
        for point in self.__kpsave:
            temp = cv2.KeyPoint(x=point[0][0], y=point[0][1], _size=point[1], _angle=point[2], _response=point[3],
                                _octave=point[4], _class_id=point[5])
            self.kp.append(temp)
    def calculateORB(self, img):
        pass #I've omitted the actual method here

(还有一些属性和方法,但它们并不相关)

现在,这个类定义在创建新实例时工作得很好:我可以创建一个只有名称的新Brick,然后我可以设置areaMin或任何其他属性,我可以使用pickle(cPickle)来转储当前实例到文件就好了(我使用那些getstate和setstate因为pickle不能使用OpenCV的Keypoint元素)。

当然,当我加载实例时出现问题:使用pickle load()我可以从文件中加载实例,我之前设置的值将在那里(即我如果我确实设置了一个值,我可以访问areaMin但是如果我从未更改过它们的值,我就无法访问任何一种方法或将值添加到任何其他属性。我注意到,如果我只是从一个完全不同的源文件中腌制,我就不需要import我的课程定义。

因为我想做的就是建立一个"数据库"从我的班级对象来看,最好的方法是什么?我知道应该工作的东西就是简单地编写一个.Save()方法来写一个.py源文件,我基本上创建了一个类的实例,这样我就可以.Load()这将适当地execeval,但是,这似乎是最糟糕的方法,所以,我该怎么做呢?

感谢。

1 个答案:

答案 0 :(得分:2)

您不应该尝试在__getstate____setstate__方法中进行I / O - 这些方法由Pickle调用,并且expted结果只是一个可以进一步腌制的内存中对象。

此外,如果你的"点" " self.kp" attribute只是一个普通的Python类,根本不需要自定义pickle -

您需要担心的是在您调用Pickle时处理I / O.如果你真的需要独立加载不同的实例,你可以诉诸"搁置"模块,或者,更好的是,使用pickle.dumps并将结果字符串存储在DBMS(可以是内置的sqlite)中。

总而言之:

class Point(object):
    ...

class Brick(object):
    def __init__(self, point, ...):
         self.kp = point

然后,将单个对象保存到文件中:

with open("filename.pickle", "wb") as file_:
    pickle.dump(my_brick, file_, -1)

并恢复:

my_brick = pickle.load(open("filename.pickle", "rb", -1)

要存储多个实例并立即恢复所有实例,可以按顺序转储到同一个打开的文件,然后逐个读取,直到您因为"空文件" - 或者您只需将要保存的所有对象添加到列表中,然后立即挑选整个列表。

要保存和检索您可以检索的任意对象,请给出一些像#34; name"或" id" - 如果您需要复杂的查询等,您可以使用搁置模块:https://docs.python.org/3/library/shelve.html或使用真实数据库。尝试编写自己的ad hoc二进制格式以允许搜索所需的实例是一个可怕的想法 - 因为您必须实现该文件的所有协议0读取,写入,保护,角落案例等。