UnpicklingError:NEWOBJ类参数不是一个类型对象

我使用了一个自定义picker,它根据来自Shane Hathaway的代码,用它们的字符串表示替换所有不可pickleable对象(如套接字或文件):Python:用一些不可取消的项目来腌制字典

它大部分时间都在工作,但是当我试图取消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()    

成功的酸洗发生在两个步骤中,Pickler的pickle.dump和Unpickler的pickle.load。 Pickler将对象转换为序列化格式(例如字符串),并且Unpickler消化pickled对象并生成应与原始对象相同的新对象。 Pickle有几个函数可以用来转储pickles ...所以第1部分就是让对象转换为序列化格式。 使用自定义pickler,你可以绕过一些python的安全措施来pickle pickle本身无法泡菜的对象。 按照你的例子,我可以创建一个简单的Pickler,通过将每个对象转换为__repr__来将lambdas和__repr__转换为字符串。

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

这肯定会被pickleable,因为它是一个字符串。 但是,问题是如何从保存的字符串构建对象。 对于一个lambda表达式,如果你有一个函数可以查找字符串中记录的内存引用,那么你可以返回对象......但只有当你的内存中仍然有原始对象存在时......那么这是不对的好。 所以转换为字符串的技巧仅在__repr__字符串中包含足够的信息以根据存储的字符串信息构建新对象时才起作用。 你可能对你存储的内容更有兴趣,但最可能的是,你最终会通过将对象转换为字符串来遇到问题。 所以这是你的Pickler工作的情况,但你的Unpickler会失败。

字典是有趣的腌制,因为他们可以有任何东西,通常做得很快。 最差的字典之一是globals()字典。 要序列化它,我会使用莳萝,它可以序列化几乎任何东西在Python中。

>>> import dill
>>> 
>>> def foo(a):
...   def bar(x):
...     return a*x
...   return bar
... 
>>> class baz(object):
...   def __call__(self, a,x):
...     return foo(a)(x)
... 
>>> b = baz()
>>> b(3,2)
6
>>> c = baz.__call__
>>> c(b,3,2)
6
>>> g = dill.loads(dill.dumps(globals()))
>>> g
{'dill': <module 'dill' from '/Library/Frameworks/Python.framework/Versions/7.2/lib/python2.7/site-packages/dill-0.2a.dev-py2.7.egg/dill/__init__.pyc'>, 'c': <unbound method baz.__call__>, 'b': <__main__.baz object at 0x4d61970>, 'g': {...}, '__builtins__': <module '__builtin__' (built-in)>, 'baz': <class '__main__.baz'>, '_version': '2', '__package__': None, '__name__': '__main__', 'foo': <function foo at 0x4d39d30>, '__doc__': None}

实际上,dill将它的类型注册到pickle注册表中,所以如果你有一些使用pickle黑盒代码,并且你不能真正编辑它,那么只需导入dill就可以神奇地使它工作,而不需要修改第三方代码。

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

>>> # 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

莳萝还有一些很好的工具,可以帮助您了解导致您的酸洗在代码失败时失败的原因。

链接地址: http://www.djcxy.com/p/64825.html

上一篇: UnpicklingError: NEWOBJ class argument isn't a type object

下一篇: Conditional use of