2017-09-08 175 views
0

我想做一个类实例的快速副本。 cPickle.loads(cPickle.dumps(),-1)工作正常,几乎比copy.deepcopy快5倍,但我read that ujson is much faster than cPickle。我无法让ujson使用自定义类,是否可以这样做?是否有可能ujson.dumps()Python类实例(更快的深度拷贝)

例如:

import cPickle as pickle 
import ujson 

class AClass(object): 
    def __init__(self): 
     print('init') 
     self.v = 10 
     self.z = [2,3,4] 
     self._zdict = dict(zip(self.z,self.z)) 

a = AClass() 
a 
#<__main__.AClass at 0x118b1d390> 


# does not work with ujson 
ua = ujson.dumps(a) 
au = ujson.loads(ua) 
au 
#{u'v': 10, u'z': [2, 3, 4]} 


# but works with pickle 
pa = pickle.dumps(a) 
ap = pickle.loads(pa) 
ap 
#<__main__.AClass at 0x117460190> 
+1

不可以。您可以通过查看ujson.dumps输出来判断(这只是一个'str'对象),它不包含重建源对象所需的信息。它只是*一个JSON编码器。这是'cPickle'更快的部分原因;它不需要做太多的事情。 – chepner

+2

我想,你必须开发自己的JSON protocole。将一个类实例转储到一个JSON对象中可能很容易(实际上是转储'__dict__')。但是,加载JSON对象并不容易:如何区分类实例的“dict”。这没有JSON语法。 –

回答

1

一个想法是定义您自己的protocole,为pickle所描述的概念的基础。在类 定义__getstate____setsatte__例如:

class AClass(object): 
    def __init__(self, v, z): 
     self.v = v 
     self.z = z 
     self._zdict = dict(zip(self.z, self.z)) 

    def __repr__(self): 
     return repr({'v': self.v, 'z': self.z, '_zdict': self._zdict}) 

    def __getstate__(self): 
     return {'v': self.v, 'z': self.z} 

    def __setstate__(self, state): 
     self.__dict__.update(state) 
     self._zdict = dict(zip(self.z, self.z)) 

然后,您可以定义一个save()load()功能是这样的:

import importlib 
import json 
import io 

def save(instance, dst_file): 
    data = { 
     'module': instance.__class__.__module__, 
     'class': instance.__class__.__name__, 
     'state': instance.__getstate__()} 
    json.dump(data, dst_file) 


def load(src_file): 
    obj = json.load(src_file) 
    module_name = obj['module'] 
    mod = importlib.import_module(module_name) 
    cls = getattr(mod, obj['class']) 
    instance = cls.__new__(cls) 
    instance.__setstate__(obj['state']) 
    return instance 

简单的使用(使用StringIO在这里,而不是一个经典的文件):

a_class = AClass(10, [2, 3, 4]) 
my_file = io.StringIO() 
save(a_class, my_file) 

print(my_file.getvalue()) 
# -> {"module": "__main__", "class": "AClass", "state": {"v": 10, "z": [2, 3, 4]}} 

my_file = io.StringIO(my_file.getvalue()) 
instance = load(my_file) 

print(repr(instance)) 
# -> {'v': 10, 'z': [2, 3, 4], '_zdict': {2: 2, 3: 3, 4: 4}} 
2

ujson不序列化对象;它只是将其属性dict编码为JSON对象。没有足够的信息来完整地再现原始对象;最明显的迹象是ujson.dumps的输出中没有记录类a是什么类。

原因usjoncPickle快得多,因为cPickle必须做更多。

+0

所以,我猜,'cPickle'是我最好的选择 – muon