python - not - 피클이 실패한 객체 속성을 알려주는 방법은 무엇입니까?




python object to json is not json serializable (3)

pickle 할 수없는 속성을 가진 객체를 pickle하면 다음과 같은 일반적인 오류 메시지와 함께 실패합니다.

PicklingError: Can't pickle <type 'instancemethod'>: attribute lookup __builtin__.instancemethod failed

어떤 속성으로 인해 예외가 발생했는지 알 수있는 방법이 있습니까? 나는 파이썬 2.5.2를 사용하고있다.

원칙적으로 문제의 근본 원인을 이해할 수 있지만 (예 : 인스턴스 메서드가있는 위의 예제에서) 정확히 정확히 파악하기는 어려울 수 있습니다 . 제 경우에는 사용자 정의 __getstate__ 메소드를 이미 정의했지만 중요한 속성은 잊어 버렸습니다. 이것은 중첩 된 객체의 복잡한 구조에서 발생했기 때문에 잘못된 속성을 식별하는 데 다소 시간이 걸렸습니다.

요청에 따라 피클이 의도적으로 실패한 간단한 예가 여기에 있습니다.

import cPickle as pickle
import new

class Test(object):
    pass

def test_func(self):
    pass

test = Test()
pickle.dumps(test)
print "now with instancemethod..."
test.test_meth = new.instancemethod(test_func, test)
pickle.dumps(test)

다음은 출력입니다.

now with instancemethod...
Traceback (most recent call last):
  File "/home/wilbert/develop/workspace/Playground/src/misc/picklefail.py", line 15, in <module>
    pickle.dumps(test)
  File "/home/wilbert/lib/python2.5/copy_reg.py", line 69, in _reduce_ex
    raise TypeError, "can't pickle %s objects" % base.__name__
TypeError: can't pickle instancemethod objects

불행히도 test_meth 속성 test_meth 인해 문제가 발생한다는 힌트는 없습니다.


나는 Pickler를 서브 클래스 화하고 Pickler.save () 메소드를 try (블록 제외) 메소드로 감싸는 경우에이를 발견했다.

import pickle
class MyPickler (pickle.Pickler):
    def save(self, obj):
        try:
            pickle.Pickler.save(self, obj)
        except Exception, e:
            import pdb;pdb.set_trace()

그런 식으로 전화하세요.

import StringIO
output = StringIO.StringIO()
MyPickler(output).dump(thingee)

나는 당신과 같은 문제가 있었지만, 클래스는 좀 더 복잡했다. (예를 들어 유사한 객체로 구성된 커다란 트리) 인쇄가 도움이되지 않아 헬퍼 함수를 ​​해킹했다. 그것은 완전하지 않으며 단지 산 세척 프로토콜 2와 함께 사용하기위한 것입니다 : 그것은 내 문제를 찾을 수있을 정도로 충분했습니다. 모든 것을 망라하도록 확장하고 싶다면, 프로토콜은 http://www.python.org/dev/peps/pep-0307/ 설명되어 있습니다 http://www.python.org/dev/peps/pep-0307/ 이 게시물을 편집 할 수있게 만들어서 모든 사람이 코드를 업데이트 할 수있게했습니다.

import pickle
def get_pickling_errors(obj,seen=None):
    if seen == None:
        seen = []
    try:
        state = obj.__getstate__()
    except AttributeError:
        return
    if state == None:
        return
    if isinstance(state,tuple):
        if not isinstance(state[0],dict):
            state=state[1]
        else:
            state=state[0].update(state[1])
    result = {}    
    for i in state:
        try:
            pickle.dumps(state[i],protocol=2)
        except pickle.PicklingError:
            if not state[i] in seen:
                seen.append(state[i])
                result[i]=get_pickling_errors(state[i],seen)
    return result

K가 피클 링하지 않는 객체 인 사용 예

>>> get_pickling_errors(K)
{'_gen': {}, '_base': {'_gens': None}}

즉, K._gen 속성은 picklable이 아니며 K._base._gens도 마찬가지입니다.


더 유용한 오류 메시지를 포함하지 않기 위해 Python에 버그를 신고 할 수 있습니다. 그 동안 _reduce_ex() 에서 _reduce_ex() 함수를 수정하십시오.

if base is self.__class__:
    print self # new   
    raise TypeError, "can't pickle %s objects" % base.__name__

산출:

<bound method ?.test_func of <__main__.Test object at 0xb7f4230c>>
Traceback (most recent call last):
  File "nopickle.py", line 14, in ?
    pickle.dumps(test)
  File "/usr/lib/python2.4/copy_reg.py", line 69, in _reduce_ex
    raise TypeError, "can't pickle %s objects" % base.__name__
TypeError: can't pickle instancemethod objects






serialization