泡菜不能与tkinter一起使用 [英] Pickle will not work with tkinter
问题描述
我正在用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.
最简单的答案是,您不能腌制任何与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列表等),则必须将它们转换为其他内容,并在启动时将其还原. /p>
I'm making a little game with Tkinter, and it has a save function using pickle. However, when I try to save, it throws up the following message;
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
The thing is, the data I'm trying to pickle contains nothing Tkinter-related, so I don't understand why it says it is <class 'tkapp'>
Here is a summary of the relevant bits of code:
...
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()
How can I fix this? I've tried changing __getstate__
as suggested in a related question, but it didn't work.
EDIT: Never mind, it turns out that deep in my data structure, I had left a BooleanVar.
The short answer is, you can't pickle anything tkinter related. The reason is that tkinter applications use an embedded Tcl interpreter which maintains the state of the GUI in memory, and Tcl doesn't know anything about the python pickle format (and likewise, pickle knows nothing about the tcl interpreter). There's simply no way to save and restore the data managed by the Tcl interpreter.
You will have to convert the information you want to save into some type of data structure, and then save and load this data structure.
For example
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"]
...
If any of the values you want to store contain references to tkinter objects (eg: widgets, list of canvas item ids, etc.), you'll have to convert them to something else, and restore them at startup.
这篇关于泡菜不能与tkinter一起使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!