2017-09-08 3 views
0

클래스 인스턴스의 빠른 복사본을 만들려고합니다. cPickle.loads(cPickle.dumps(),-1)copy.deepcopy보다 거의 5 배 빠르지 만 I read that ujson is much faster than cPickle과 비슷합니다. 나는 ujson이 맞춤 클래스로 작업하도록 할 수 없었습니다. 그렇게 할 수 있습니까?ujson.dumps() 파이썬 클래스 인스턴스 (빠른 딥 카피) 가능합니다

예 :

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이 어떤 인스턴스인지 기록하지 않는다는 것입니다.

이유는 usjoncPickle보다 훨씬 빠르기 때문에 cPickle은 훨씬 더 많은 작업을 수행해야한다는 것입니다.

+0

그래서, 'cPickle'이 내 최선의 방법이라고 생각해. – muon

관련 문제