无法使用pickle序列化instancemethod对象。

4

我遇到了一个关于pickle的问题,代码如下:

import cPickle

class A(object):

    def __init__(self):
        self.a = 1

    def methoda(self):
        print(self.a)


class B(object):

    def __init__(self):
        self.b = 2
        a = A()
        self.b_a = a.methoda

    def methodb(self):
        print(self.b)
if __name__ == '__main__':
    b = B()
    with open('best_model1.pkl', 'w') as f:
        cPickle.dump(b, f)

错误信息如下:

文件 "/usr/lib/python2.7/copy_reg.py",第70行,函数_reduce_ex()中, 抛出TypeError异常,原因是无法将%base.name对象进行序列化。TypeError: 无法序列化instancemethod对象。

2个回答

3

如果您使用dill而不是cPickle,则可以实现。

>>> import dill     
>>> 
>>> class A(object):
...   def __init__(self):
...     self.a = 1
...   def methods(self):
...     print(self.a)
... 
>>> 
>>> class B(object):
...   def __init__(self):
...     self.b = 2
...     a = A()
...     self.b_a = a.methods
...   def methodb(self):
...     print(self.b)
... 
>>> b = B()
>>> b_ = dill.dumps(b)
>>> _b = dill.loads(b_)
>>> _b.methodb()
2
>>> 

另请参见:使用Python的multiprocessing Pool.map()时,无法pickle<type 'instancemethod'>


除了替换之外,还有其他解决这个问题的方法吗? - DemoRunner
1
如果你看一下dill在做什么,它只是在copyreg中注册序列化函数。如果你想的话,你也可以这样做...基本上,注册与dill使用相同的序列化函数,然后pickle将像上面那样为你工作。 - Mike McKerns

0
此外,当安装了dill时,pickle将会工作,但通常不支持cPickle。
import cPickle, pickle

class A(object):
    def __init__(self):
        self.a = 1
    def methoda(self):
        print(self.a)

class B(object):
    def __init__(self):
        self.b = 2
        a = A()
        self.b_a = a.methoda
    def methodb(self):
        print(self.b)

# try using cPickle
try:
    c = cPickle.dumps(b)
    d = cPickle.loads(c)
except Exception as err:
    print('Unable to use cPickle (%s)'%err)
else:
    print('Using cPickle was successful')
    print(b)
    print(d)

# try using pickle
try:
    c = pickle.dumps(b)
    d = pickle.loads(c)
except Exception as err:
    print('Unable to use pickle (%s)'%err)
else:
    print('Using pickle was successful')
    print(b)
    print(d)

 >>> Unable to use cPickle (can't pickle instancemethod objects)
 >>> Using pickle was successful
 >>> <__main__.B object at 0x10e9b84d0>
 >>> <__main__.B object at 0x13df07190>

出于某种原因,cPickle并不仅仅是pickle的C版本,速度快100倍,而是存在一些差异。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接