Tkinter 删除已pickle的变量

Tkinter 删除已pickle的变量,tkinter,pickle,python-2.x,shelve,del,Tkinter,Pickle,Python 2.x,Shelve,Del,谈到Python,我并不十分熟练,但我真的让自己陷入了困境。撇开双关语不谈,我正在使用Tkinter,我有一个特殊的函数,让我可以轻松保存所有全局变量: def start_save(globals_=None) : global quick_save_file, options if globals_ is None: globals_ = globals() the_file = tkFileDialog.asksaveasfilename(**fil

谈到Python,我并不十分熟练,但我真的让自己陷入了困境。撇开双关语不谈,我正在使用Tkinter,我有一个特殊的函数,让我可以轻松保存所有全局变量:

def start_save(globals_=None) :
    global quick_save_file, options
    if globals_ is None:
        globals_ = globals()
    the_file = tkFileDialog.asksaveasfilename(**file_opt) 
    my_shelf = shelve.open(the_file,'c') # 'n' for new
    for key, value in globals_.items():
        if not key.startswith('__'):
            try:
                my_shelf[key] = globals()[key]
                add_line( "Saved %r" % key)
            except TypeError:
                # __builtins__, my_shelf, and imported modules can not be shelved.
                add_line(('ERROR shelving: {0}'.format(key)))
            except :
                add_line( "Cannot pickle %r" % key)
    quick_save_file = the_file
    options['initialfile'] = quick_save_file
    my_shelf.close()
基本上,我们看的是试用后会发生什么:它将我所有的全局内容保存到用户选择的文件中。现在,我知道Tkinter小部件无法保存,但我意外地创建了一个小部件,并将其网格化在同一行上,如下所示:

ldrones_e = Label(frame_drones, text = "Number of drones:").grid(row = 3, column = 1, columnspan = 2)
这导致我的搁置函数将其读取为None,而不是widget!因此,它不是说它不能用它做任何事情,而是将它保存为“无”。现在,当我打开这个文件时,它接受我的widget变量并将其设置为none。我不能在单独的行上使用.grid保存它,因为这样它就不会被保存。我不能使用del删除变量,因为它位于不同的文件中。(事实上,我可能可以,我只是不知道该怎么做)


因此,我的问题是如何从pickle文件中删除讨厌的ldrones_e变量,以便我的程序将使用新的ldrones_e变量,该变量没有附加.grid。

如果必须,可以手动删除pickle的相关部分。这可以通过使用pickletools.dis实现。但是,您必须了解pickle的递归工作方式。pickle是通过递归到一个对象中,并在对象本身可以被pickle之前对其状态依赖项进行pickle…然后对所有依赖项进行类似的递归…等等,直到特定的递归分支命中一个不需要依赖项来pickle的对象为止。然后,一旦所有依赖项对象都被pickle了,您最终就完成了

在这里,您可以看到
pickletools.dis
显示pickle的每个部分:

>>> import pickletools
>>> import pickle   
>>> pik = pickle.dumps(dict(zip(list('abcde'),[1,2,3,4,5])))
>>> pickletools.dis(pik)
    0: (    MARK
    1: d        DICT       (MARK at 0)
    2: p    PUT        0
    5: S    STRING     'a'
   10: p    PUT        1
   13: I    INT        1
   16: s    SETITEM
   17: S    STRING     'c'
   22: p    PUT        2
   25: I    INT        3
   28: s    SETITEM
   29: S    STRING     'b'
   34: p    PUT        3
   37: I    INT        2
   40: s    SETITEM
   41: S    STRING     'e'
   46: p    PUT        4
   49: I    INT        5
   52: s    SETITEM
   53: S    STRING     'd'
   58: p    PUT        5
   61: I    INT        4
   64: s    SETITEM
   65: .    STOP
highest protocol among opcodes = 0
>>> pik
"(dp0\nS'a'\np1\nI1\nsS'c'\np2\nI3\nsS'b'\np3\nI2\nsS'e'\np4\nI5\nsS'd'\np5\nI4\ns."
这里是dill
dill
,展示了一件物品腌制的路线。像
F1:…
这样的打印输出是对象酸洗的开始,而
#F1
是对象酸洗的结束:

>>> import dill
>>> dill.detect.trace(True)
>>> dill.dumps(dict(zip(list('abcde'),[1,2,3,4,5])))
D2: <dict object at 0x10c5c9e88>
# D2
'\x80\x02}q\x00(U\x01aq\x01K\x01U\x01cq\x02K\x03U\x01bq\x03K\x02U\x01eq\x04K\x05U\x01dq\x05K\x04u.'
>>> 
>>> def foo(x):
...   def bar(y):
...     return x+y
...   return bar
... 
>>> dill.dumps(foo)
F1: <function foo at 0x10c60a9b0>
F2: <function _create_function at 0x10c5a68c0>
# F2
Co: <code object foo at 0x10b6130b0, file "<stdin>", line 1>
F2: <function _unmarshal at 0x10c5a6758>
# F2
# Co
D1: <dict object at 0x10b51a168>
# D1
D2: <dict object at 0x10c5c4910>
# D2
# F1
'\x80\x02cdill.dill\n_create_function\nq\x00(cdill.dill\n_unmarshal\nq\x01U\xd6c\x01\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00s\x13\x00\x00\x00\x87\x00\x00f\x01\x00d\x01\x00\x86\x00\x00}\x01\x00|\x01\x00S(\x02\x00\x00\x00Nc\x01\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x13\x00\x00\x00s\x08\x00\x00\x00\x88\x00\x00|\x00\x00\x17S(\x01\x00\x00\x00N(\x00\x00\x00\x00(\x01\x00\x00\x00t\x01\x00\x00\x00y(\x01\x00\x00\x00t\x01\x00\x00\x00x(\x00\x00\x00\x00s\x07\x00\x00\x00<stdin>t\x03\x00\x00\x00bar\x02\x00\x00\x00s\x02\x00\x00\x00\x00\x01(\x00\x00\x00\x00(\x02\x00\x00\x00R\x01\x00\x00\x00R\x02\x00\x00\x00(\x00\x00\x00\x00(\x01\x00\x00\x00R\x01\x00\x00\x00s\x07\x00\x00\x00<stdin>t\x03\x00\x00\x00foo\x01\x00\x00\x00s\x04\x00\x00\x00\x00\x01\x0f\x02q\x02\x85q\x03Rq\x04c__builtin__\n__main__\nU\x03fooq\x05NN}q\x06tq\x07Rq\x08.'
>>> 
>>> dill.detect.trace(False)
我们退出,并开始一个新的口译员会话:

Python 2.7.10 (default, May 25 2015, 13:16:30) 
[GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.40)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import klepto
>>> d = klepto.archives.dir_archive('saveme', serialized=True, cached=False)
>>> d.keys()
['pickletools', 'dill', 'pik', 'd', '__builtins__', 'klepto', '__package__', '__name__', 'foo', 'pickle', '__doc__']
>>> for i,j in d.items():
...   globals()[i] = j       
... 
>>> foo(3)(4)
7
>>> 
每个对象都可以从它自己的文件中单独访问…因此您可以简单地
pop
其中一个对象。您还可以使用
cached=True
,并将任何您喜欢的对象加载到内存中(未显示)--使用
cached=False
,不会将任何对象加载到内存中,并且直接与文件后端交互

>>> x = d.pop('d')
>>> del d['pik'], x
>>> d.keys()
['pickletools', 'dill', '__builtins__', 'klepto', '__package__', '__name__', 'foo', 'pickle', '__doc__']
>>> d['foo'](3)(4)
7

您是否尝试过使用
del
命令简单地删除变量?然后重新pickle文件?如果我删除变量并使用shelving方法重新pickle,它只会保留旧变量,因为没有新的变量来替换它。除非您的意思是删除变量并将所有内容搁置到一个全新的文件中。在这种情况下,它可以工作,但会给其他用户带来不便。
>>> x = d.pop('d')
>>> del d['pik'], x
>>> d.keys()
['pickletools', 'dill', '__builtins__', 'klepto', '__package__', '__name__', 'foo', 'pickle', '__doc__']
>>> d['foo'](3)(4)
7