我的项目的一个重要部分是能够将类实例保存并加载到文件中。对于进一步的上下文,我的类既有一组属性,也有一些方法。
到目前为止,我已尝试使用 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()
这将适当地exec
和eval
,但是,这似乎是最糟糕的方法,所以,我该怎么做呢?
感谢。
答案 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读取,写入,保护,角落案例等。