我的项目的一个重要部分是能够将类实例保存和加载到文件中。对于进一步的上下文,我的类既有一组属性又有一些方法。
到目前为止,我已经尝试使用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
Run Code Online (Sandbox Code Playgroud)
(还有一些属性和方法,但它们不相关)
现在,这个类定义在创建新实例时工作得很好:我可以只用名称创建一个新的 Brick,然后我可以设置 areaMin 或任何其他属性,我可以使用 pickle(cPickle) 将当前实例转储到文件中很好(我正在使用那些 getstate 和 setstate 因为 pickle 不适用于 OpenCV 的 Keypoint 元素)。
当然,当我加载实例时,问题就来了:使用 pickle load() 我可以从文件加载实例,并且我之前设置的值将在那里(即,如果我确实设置了一个,我可以很好地访问 areaMin值),但如果我从未更改过它们的值,我将无法访问任一方法或向任何其他属性添加值。我注意到import如果我只是从一个完全不同的源文件中进行酸洗,我也不需要我的类定义。
由于我想要做的就是从我的类对象构建一个“数据库”,那么解决这个问题的最佳方法是什么?我知道的东西应该工作是简单地写了.Save()一个写入的.py源文件,其中我基本上创建类的实例方法,所以我可以那么.Load()它会做exec和eval适当的,但是,这似乎是最糟糕的方式这样做,那么,我应该怎么做呢?
谢谢。
您不应该尝试在您的__getstate__和__setstate__方法中执行 I/O - 这些由 Pickle 调用,并且扩展结果只是一个可以进一步腌制的内存中对象。
此外,如果您在“self.kp”属性中的“Point”类只是一个普通的 Python 类,那么您根本不需要自定义酸洗 -
您需要担心的是在您调用 Pickle 时处理 I/O。如果您真的需要独立加载不同的实例,您可以使用“搁置”模块,或者更好的是,使用 pickle.dumps 并将结果字符串存储在 DBMS(可以是内置的 sqlite)中。
总而言之:
class Point(object):
...
class Brick(object):
def __init__(self, point, ...):
self.kp = point
Run Code Online (Sandbox Code Playgroud)
然后,要将单个对象保存到文件:
with open("filename.pickle", "wb") as file_:
pickle.dump(my_brick, file_, -1)
Run Code Online (Sandbox Code Playgroud)
并恢复:
my_brick = pickle.load(open("filename.pickle", "rb", -1)
Run Code Online (Sandbox Code Playgroud)
要存储多个实例并一次恢复所有实例,您可以依次转储到同一个打开的文件中,然后它们一个一个地读取,直到由于“空文件”而出现错误 - 或者您可以简单地添加您想要的所有对象保存到列表,并一次腌制整个列表。
要保存和检索您可以检索的任意对象,例如“名称”或“ID”之类的属性 - 您可以求助于搁置模块:https : //docs.python.org/3/library/shelve.html或使用真正的数据库,如果您需要复杂的查询等。尝试编写自己的临时二进制格式以允许搜索所需的实例是一个可怕的想法 - 因为您必须为该文件 0 读取、写入、保护、极端情况等实现所有协议。
| 归档时间: |
|
| 查看次数: |
9220 次 |
| 最近记录: |