2017-09-08 6 views
0

私はクラスインスタンスの高速コピーを作成しようとしています。 cPickle.loads(cPickle.dumps(),-1)は、copy.deepcopyよりもほぼ5倍速いですが、I 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プロトコールを開発しなければならないと思います。クラスインスタンスをJSONオブジェクトにダンプすることは簡単です(実際は '__dict__'をダンプします)。しかし、JSONオブジェクトをロードするのは簡単ではありません。クラス・インスタンスから 'dict'をどうやって区別しますか?そのためのJSON構文はありません。 –

答えて

1

考えられるのは、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がインスタンスであったかを記録していません。

理由はusjonは、cPickleよりもずっと速く、cPickleはもっと多くのことをしなければならないということです。

+0

だから、 'cPickle'が私の最高の賭けだと思います – muon

関連する問題