gpt4 book ai didi

Python:用一些不可 pickle 的项目 pickle 字典

转载 作者:太空狗 更新时间:2023-10-29 18:06:53 27 4
gpt4 key购买 nike

我有一个对象 gui_project,它有一个属性 .namespace,这是一个命名空间字典。 (即从字符串到对象的字典。)

(这在类似 IDE 的程序中使用,让用户在 Python shell 中定义自己的对象。)

我想 pickle 这个 gui_project 以及命名空间。问题是,命名空间中的某些对象(即 .namespace dict 的值)不是可 picklable 对象。例如,其中一些引用了 wxPython 小部件。

我想过滤掉不可 picklable 的对象,即将它们从 pickled 版本中排除。

我该怎么做?

(我尝试过的一件事是一个一个地处理值并尝试 pickle 它们,但是发生了一些无限递归,我需要避免这种情况。)

(我现在确实实现了一个 GuiProject.__getstate__ 方法,以摆脱 namespace 之外的其他不可修改的东西。)

最佳答案

我会使用 pickler 对持久对象引用的文档化支持。持久对象引用是由 pickle 引用但未存储在 pickle 中的对象。

http://docs.python.org/library/pickle.html#pickling-and-unpickling-external-objects

ZODB 多年来一直使用此 API,因此非常稳定。 unpickling 时,您可以将对象引用替换为您喜欢的任何内容。在您的情况下,您可能希望用指示无法 pickle 对象的标记替换对象引用。

你可以从这样的东西开始(未经测试):

import cPickle

def persistent_id(obj):
if isinstance(obj, wxObject):
return "filtered:wxObject"
else:
return None

class FilteredObject:
def __init__(self, about):
self.about = about
def __repr__(self):
return 'FilteredObject(%s)' % repr(self.about)

def persistent_load(obj_id):
if obj_id.startswith('filtered:'):
return FilteredObject(obj_id[9:])
else:
raise cPickle.UnpicklingError('Invalid persistent id')

def dump_filtered(obj, file):
p = cPickle.Pickler(file)
p.persistent_id = persistent_id
p.dump(obj)

def load_filtered(file)
u = cPickle.Unpickler(file)
u.persistent_load = persistent_load
return u.load()

然后只需调用 dump_filtered() 和 load_filtered() 而不是 pickle.dump() 和 pickle.load()。 wxPython 对象将被 pickle 为持久 ID,在 unpickling 时被 FilteredObjects 替换。

您可以通过过滤掉不属于内置类型且没有 __getstate__ 方法的对象来使解决方案更通用。

更新(2010 年 11 月 15 日):这是一种使用包装类实现相同目的的方法。使用包装器类而不是子类,可以保留在记录的 API 中。

from cPickle import Pickler, Unpickler, UnpicklingError


class FilteredObject:
def __init__(self, about):
self.about = about
def __repr__(self):
return 'FilteredObject(%s)' % repr(self.about)


class MyPickler(object):

def __init__(self, file, protocol=0):
pickler = Pickler(file, protocol)
pickler.persistent_id = self.persistent_id
self.dump = pickler.dump
self.clear_memo = pickler.clear_memo

def persistent_id(self, obj):
if not hasattr(obj, '__getstate__') and not isinstance(obj,
(basestring, int, long, float, tuple, list, set, dict)):
return "filtered:%s" % type(obj)
else:
return None


class MyUnpickler(object):

def __init__(self, file):
unpickler = Unpickler(file)
unpickler.persistent_load = self.persistent_load
self.load = unpickler.load
self.noload = unpickler.noload

def persistent_load(self, obj_id):
if obj_id.startswith('filtered:'):
return FilteredObject(obj_id[9:])
else:
raise UnpicklingError('Invalid persistent id')


if __name__ == '__main__':
from cStringIO import StringIO

class UnpickleableThing(object):
pass

f = StringIO()
p = MyPickler(f)
p.dump({'a': 1, 'b': UnpickleableThing()})

f.seek(0)
u = MyUnpickler(f)
obj = u.load()
print obj

assert obj['a'] == 1
assert isinstance(obj['b'], FilteredObject)
assert obj['b'].about

关于Python:用一些不可 pickle 的项目 pickle 字典,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4080688/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com