Удалить переменную, которая была засолена
Я не совсем знаток, когда дело доходит до 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, а не виджет! Поэтому вместо того, чтобы сказать, что ничего не может с этим поделать, он сохранил его как None. Теперь, когда я открываю указанный файл, он берет мою переменную виджета и устанавливает ее в none. Я не могу сохранить поверх этого, с.grid на отдельной строке, потому что тогда он не будет сохранен. Я не могу использовать del, чтобы избавиться от переменной, потому что она находится в другом файле. (На самом деле, я, вероятно, могу, я просто не знаю, как это сделать)
Поэтому мой вопрос заключается в том, как мне удалить эту надоедливую переменную ldrones_e из моего файла pickle, чтобы моя программа использовала новую переменную ldrones_e, к которой не привязан.grid.
1 ответ
Если вам абсолютно необходимо, вы можете удалить соответствующие части маринада вручную. Это может быть возможно с помощью pickletools.dis
... однако вы должны понимать рекурсивный способ, которым работает рассол. 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
Вы можете сохранить каждый объект в dict как консервированный объект в другой файл в пределах одного каталога.
>>> 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