保存和加载类实例从文件

2024-09-29 23:21:56 发布

您现在位置:Python中文网/ 问答频道 /正文

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

到目前为止,我已经尝试过使用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

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

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

当然,当我加载实例时,问题就来了:使用pickle load()可以从文件加载实例,我之前设置的值也会在那里(即我可以访问areaMin,如果我为它设置了一个值的话),但是如果我从未更改它们的值,我就不能访问任何方法或向任何其他属性添加值。我注意到,如果我只是从一个完全不同的源文件中进行pickle,我也不需要import我的类定义。在

既然我只想从类对象中构建一个“数据库”,那么最好的方法是什么?我知道应该工作的是简单地编写一个.Save()方法,该方法编写一个.py源文件,在那里我基本上创建了一个类的实例,这样我就可以.Load()根据需要执行exec和{},但是,这似乎是最糟糕的方法了,那么,我应该怎么做呢?在

谢谢。在


Tags: 实例方法nameselfnone属性deffilename
1条回答
网友
1楼 · 发布于 2024-09-29 23:21:56

您不应该尝试在您的__getstate____setstate__方法中执行I/O操作,这些方法由Pickle调用,而导出的结果只是内存中的一个对象,可以进一步Pickle。在

而且,如果你的“点”课自我.kp“attribute只是一个普通的Python类,根本不需要定制pickling-

您需要担心的是在您称之为Pickle的点处理I/O。如果您真的需要独立地加载不同的实例,可以使用“shelve”模块,或者更好地使用泡菜、垃圾并将生成的字符串存储在DBMS(可以是内置的sqlite)中。在

总而言之:

class Point(object):
    ...

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

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

^{pr2}$

并恢复为:

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

要存储多个实例并一次恢复所有实例,您可以将这些实例依次转储到同一个打开的文件中,然后它们逐个读取,直到您因“空文件”而出现错误;或者您可以简单地将所有要保存的对象添加到一个列表中,然后一次对整个列表进行pickle。在

要保存和检索可以检索的任意对象,您可以使用shelve模块:https://docs.python.org/3/library/shelve.html或使用真实的数据库(如果您需要复杂的查询等)。尝试编写自己的特别二进制格式以允许搜索所需实例是一个可怕的想法-因为您必须实现文件0的所有协议,读取、写入、保护、角落案例等等。在

相关问题 更多 >

    热门问题