我有以下方法:
def save(self):
vertices = self.mindmap.get_vertices()
edges = self.mindmap.get_edges()
output = open('mindmap.pkl', 'wb')
pickle.dump(edges, output)
pickle.dump(vertices, output)
output.close()
当我调用这个方法时,我得到以下错误:
Traceback (most recent call last):
File "main.py", line 72, in <module>
MindMapApp().run()
File "/Applications/Kivy.app/Contents/Resources/kivy/kivy/app.py", line 792, in run
runTouchApp()
File "/Applications/Kivy.app/Contents/Resources/kivy/kivy/base.py", line 481, in runTouchApp
EventLoop.window.mainloop()
File "/Applications/Kivy.app/Contents/Resources/kivy/kivy/core/window/window_pygame.py", line 381, in mainloop
self._mainloop()
File "/Applications/Kivy.app/Contents/Resources/kivy/kivy/core/window/window_pygame.py", line 287, in _mainloop
EventLoop.idle()
File "/Applications/Kivy.app/Contents/Resources/kivy/kivy/base.py", line 324, in idle
self.dispatch_input()
File "/Applications/Kivy.app/Contents/Resources/kivy/kivy/base.py", line 309, in dispatch_input
post_dispatch_input(*pop(0))
File "/Applications/Kivy.app/Contents/Resources/kivy/kivy/base.py", line 275, in post_dispatch_input
wid.dispatch('on_touch_up', me)
File "_event.pyx", line 316, in kivy._event.EventDispatcher.dispatch (kivy/_event.c:4537)
File "/Applications/Kivy.app/Contents/Resources/kivy/kivy/uix/behaviors.py", line 110, in on_touch_up
self.dispatch('on_release')
File "_event.pyx", line 312, in kivy._event.EventDispatcher.dispatch (kivy/_event.c:4491)
File "/Applications/Kivy.app/Contents/Resources/kivy/kivy/lang.py", line 1299, in custom_callback
exec(__kvlang__.co_value, idmap)
File "./mindmap.kv", line 14, in <module>
on_release: app.save()
File "main.py", line 27, in save
pickle.dump(vertices, output)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1370, in dump
Pickler(file, protocol).dump(obj)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 224, in dump
self.save(obj)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 600, in save_list
self._batch_appends(iter(obj))
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 615, in _batch_appends
save(x)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 306, in save
rv = reduce(self.proto)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/copy_reg.py", line 71, in _reduce_ex
state = base(self)
TypeError: __init__() takes exactly 0 positional arguments (1 given)
如果两个数组都为空,则不会出现此错误。当生成上述内容时,edges
为空,而vertices
的大小为1。我真的不知道如何解释这个错误,也不知道如何解决它
这是我的Vertex
类__init__
:
def __init__(self, pos=None, size=None):
super(Vertex, self).__init__()
self.pos = pos
self.size = size
if self.height < self.MINIMUM_HEIGHT + self.TEXT_OFFSET:
self.height = self.MINIMUM_HEIGHT + self.TEXT_OFFSET
if self.width < self.MINIMUM_WIDTH + self.TEXT_OFFSET:
self.width = self.MINIMUM_WIDTH + self.TEXT_OFFSET
self.originalSize = self.size
self.originalWidth = self.size[0]
self.newIdea = TextInput(
height = self.MINIMUM_HEIGHT,
size_hint = (None, None),
pos_hint = {'center_x':.5, 'center_y':.5},
background_active = '',
background_normal = '',
use_bubble = True,
foreground_color = (.4, .4, .4, 1),
cursor_color = (.4, .4, .4, 1))
self.newIdea.bind(text=self.on_text)
self.idea = Label(
height = self.MINIMUM_HEIGHT,
size_hint = (None, None),
pos_hint = {'center_x':.5, 'center_y':.5},
color = (.4, .4, .4,1))
Logger.info('Vertex: created')
实际上,Kivy EventDispatcher
对象在这里有错误;object.__reduce_ex__
方法搜索不是自定义类的第一个基类(它没有设置Py_TPFLAGS_HEAPTYPE
标志(以在该类上调用__init__
对于该基类,这将失败,因为它的__init__
方法不支持传入单个参数。
解决办法是使用最新的pickle协议;它使用不同的代码路径:
pickle.dump(edges, output, pickle.HIGHEST_PROTOCOL)
pickle.dump(vertices, output, pickle.HIGHEST_PROTOCOL)
因为最新的pickle协议(2(更有效地支持新型类。
鉴于Kivy对象层次结构的复杂性,您可能需要自定义酸洗过程。
我会考虑实现__getnewargs__
方法,例如:
def __getnewargs__(self):
return (self.pos, self.size)
将确保只是数据被腌制,仅此而已。在取消拾取时,这两个值将用于创建新的Vertex
对象。请注意,要使用此方法,必须使用最新协议!
您还可以实现__getstate__
方法;如果返回字典,则不需要镜像__setstate__
方法,但将允许您初始化更多属性。
如果两者都不实现,则改为对实例__dict__
的内容进行pickle。确保中包含的所有东西都可以腌制。