2015-10-01 47 views
0

當我提到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) 

這引起了我的書架功能,它讀成無,而不是一個小部件!所以不是說它不能做任何事情,而是將它保存爲無。現在,當我打開所述文件時,它會佔用我的小部件變量並將其設置爲無。我無法保存它,在單獨的行上使用.grid,因爲它不會被保存。我不能使用del來擺脫變量,因爲它在不同的文件中。 (實際上,我可能可以,我只是不知道如何做到這一點)

所以我的問題是如何從我的pickle文件中刪除那個討厭的ldrones_e變量,所以我的程序將使用新的ldrones_e變量沒有.grid附加到它。

+0

你試過簡單地用'del'命令刪除變量嗎?然後重新酸洗文件? –

+0

如果我使用shelving方法刪除變量並重新使用pickle,它會保留舊的變量,因爲沒有新的變量替代它。除非你的意思是刪除變量並將所有內容都擱置到一個全新的文件中。在這種情況下,它會起作用,但會給其他用戶帶來不便。 – Lentro

回答

1

如果您絕對必須,您可以手動刪除醬菜的相關部分。這可以使用pickletools.dis ...但是,您必須瞭解pickle工作的遞歸方式。 Pickles是通過遞歸到一個對象中進行的,並且在對象本身可以被醃製之前醃製它的狀態依賴關係...然後對於所有依賴關係類似地遞歸地進行...等等,直到該特定的遞歸分支到達不需要依賴關係的對象泡菜。然後,一旦所有的依賴對象被醃製,你終於完成了。

在這裏你可以看到pickletools.dis展示泡菜的每一個部分是什麼:

>>> 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,顯示出的一個項目,以酸洗路線。像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) 

不過,我最好的建議是,如果你打算從泡菜刪除對象,然後在更鹹菜明智的方式......讓我們說你想醃製對象的字典(如globals()中的所有內容)。通過使用klepto,可以將每個對象作爲pickle對象保存在一個字典中,並將其保存爲單個目錄中的不同文件。

>>> import klepto 
>>> d = klepto.archives.dir_archive('saveme', serialized=True, cached=False) 
>>> d.update(globals()) 
>>> d.keys() 
['pickletools', 'dill', 'pik', 'd', '__builtins__', 'klepto', '__package__', '__name__', 'foo', 'pickle', '__doc__'] 
>>> 

我們不幹了,並開始了新的解釋器會話:

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