UnpicklingError:NEWOBJ类参数不是obj类型

2024-04-29 16:22:01 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用一个自定义pickler,它将任何不可pickle的对象(如套接字或文件)替换为它们的字符串表示形式,它基于Shane Hathaway的代码: Python: Pickling a dict with some unpicklable items

它在大多数情况下都是有效的,但是当我试图取消对Django HttpResponse的拾取时,会出现以下错误: UnpicklingError:NEWOBJ类参数不是类型对象

我不知道这个错误到底是什么意思。如果它腌好了,为什么它不能解开呢?我在Google上找到了三个关于这个错误的参考,但是没有真正解释为什么会发生或者如何修复它。在

这是我的代码:

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=2):
        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, bool, int, long, float, complex, tuple, list, set, dict)):
            return ["filtered:%s" % str(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[0].startswith('filtered:'):
            return FilteredObject(obj_id[0][9:])
        else:
            raise UnpicklingError('Invalid persistent id')

###### serialize to file

f = open('test.txt','wb')
p = MyPickler(f)
p.dump(data)
f.close()

###### unserialize from file

f = open('test.txt','rb')
pickled_data = f.read()
f.seek(0)
u = MyUnpickler(f)
data = u.load()    

Tags: selfidobjreturndef错误loadclass
1条回答
网友
1楼 · 发布于 2024-04-29 16:22:01

成功的酸洗发生在两个步骤中泡菜。倾倒在腌菜工人旁边,还有酸洗。装载由拆弹者。Pickler将一个对象转换为序列化格式(例如字符串),Unpickler对Pickler对象进行消化并生成一个新的对象,该对象应该与原始对象等价。Pickle有几个函数可以用来转储Pickle。。。因此,第1部分是将对象转换为序列化格式。使用自定义pickler,您可以绕过python的一些保护措施来pickle pickle本身无法pickle的对象。按照您的例子,我可以创建一个简单的Pickler,通过将每个对象转换为它的__repr__,将lambdas和whatnot转换为字符串。在

>>> x = lambda x:x
>>> repr(x)
'<function <lambda> at 0x4d39cf0>'
>>> 
>>> import pickle
>>> l = repr(x)
>>> pickle.dumps(l)
"S'<function <lambda> at 0x4d39cf0>'\np0\n."

这肯定是可以腌制的,因为它是一根线。但是,问题是如何从保存的字符串构建对象。对于lambda,如果你有一个可以查找内存的函数 引用在字符串中,你可以把对象取回。。。但前提是你还有 你记忆中的原始物体。。。所以这不好。因此,只有当__repr__字符串中包含足够的信息来根据存储的字符串信息构建一个新对象时,转换为字符串的技巧才有效。你可以对你存储的内容有更高的要求,但是你最终会遇到问题,很可能是将对象转换成字符串。所以这是一个例子,你的泡菜机可以工作,但你的解酒器会失败。在

词典很有趣,因为字典里可以有任何东西,而且通常很快就能查出来。最讨厌的字典之一是globals()字典。为了序列化它,我使用dill,它几乎可以序列化python中的任何内容。在

^{pr2}$

实际上,dill将它的类型注册到pickle注册表中,因此,如果您有一些使用pickle的黑盒代码,并且您不能真正编辑它,那么只需导入dill就可以神奇地使它工作,而不必对第三方代码进行monkey修补。在

或者,如果您希望整个解释器会话作为“python映像”发送,dill也可以这样做。在

>>> # continuing from above
>>> dill.dump_session('foobar.pkl')
>>>
>>> ^D
dude@sakurai>$ python
Python 2.7.5 (default, Sep 30 2013, 20:15:49) 
[GCC 4.2.1 (Apple Inc. build 5566)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import dill
>>> dill.load_session('foobar.pkl')
>>> c(b,3,2)
6

Dill还有一个some good tools,可以帮助您理解当代码失败时,是什么导致了酸洗失败。在

相关问题 更多 >