我正在与Tkinter进行一场小游戏,它有一个使用pickle的保存功能。但是,当我尝试保存时,它会抛出以下消息;
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python34\lib\tkinter\__init__.py", line 1533, in __call__
return self.func(*args)
File "C:\Users\Benedict\Documents\Python\Migrant Simulator\MigSim 2016.10\migrant-stimulator.py", line 260, in save
pickle.dump(self.game,file)
_pickle.PicklingError: Can't pickle <class 'tkapp'>: attribute lookup tkapp on __main__ failed
问题是,我试图腌制的数据不包含与Tkinter相关的数据,所以我不明白为什么它说<class 'tkapp'>
以下是相关代码位的摘要:
...
class Game(object):
def __init__(self,name,nodes={},start=None,history=[]):
self.name=name
self.nodes=nodes
self.start=start
self.history=history
class App:
def __init__(self, master):
self.master=master
...
def save(self):
if self.file_name==None:
self.save_as()
file=open(self.file_name,'wb')
pickle.dump(self.game,file) # self.game is an instance of the Game class defined elsewhere
print(str(type(self.game)))
file.close()
def save_as(self):
self.file_name=filedialog.asksaveasfilename()
self.save()
...
root = Tk()
app = App(root)
root.mainloop()
我该如何解决这个问题?我已按照相关问题的建议尝试更改__getstate__
,但它没有用。
编辑:没关系,事实证明,在我的数据结构中,我留下了一个BooleanVar。
答案 0 :(得分:2)
简短的回答是,你不能腌制与tkinter相关的任何东西。原因是tkinter应用程序使用嵌入式Tcl解释器来维护内存中GUI的状态,而Tcl对python pickle格式一无所知(同样,pickle对tcl解释器一无所知)。根本无法保存和恢复由Tcl解释器管理的数据。
您必须将要保存的信息转换为某种类型的数据结构,然后保存并加载此数据结构。
例如
def save(self):
data = {"name": self.name,
"nodes": self.nodes,
...
}
with open('data.json', 'w') as f:
json.dump(data, f)
def load(self):
with open('data.json') as f:
data = json.load(f)
self.name = data["name"]
self.nodes = data["nodes"]
...
如果您要存储的任何值包含对tkinter对象的引用(例如:小部件,画布项ID列表等),您必须将它们转换为其他值,并在启动时恢复它们
答案 1 :(得分:0)
除了Brian Oakley提出的建议之外,还可以将数据另存为莳萝导出:
def save(self):
data = {"name": self.name,
"nodes": self.nodes,
...
}
with open('data.pkl', 'wb') as f:
dill.dump(data, f)
def load(self):
with open('data.pkl', 'rb') as f:
data = dill.load(f)
self.name = data["name"]
self.nodes = data["nodes"]
...
请注意,在此处必须在打开文件时指定二进制模式。