2016-10-25 7 views
0

Я делаю небольшую игру с Tkinter, и у нее есть функция сохранения с использованием pickle. Однако, когда я пытаюсь сохранить, он выдает следующее сообщение;Pickle не работает с tkinter

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.

+1

Что такое 'self.game'? – furas

+0

@furas извините, это экземпляр игры, я добавлю его на свой вопрос –

+0

. Вы сохраняете какие-либо элементы tkinter в Game-классе? – furas

ответ

0

Короткий ответ: вы не можете определить, что связано с tkinter. Причина в том, что приложения tkinter используют встроенный интерпретатор Tcl, который поддерживает состояние графического интерфейса в памяти, а 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 объектов (например, виджеты, список брезентовых элементов идентификаторов и т.д.), вы должны преобразовать их в что-то еще, и восстановить их при запуске.