2017-09-08 84 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