9

私は非常に複雑なオブジェクト階層をピクルしようとしていますが、例外が発生しています:

pickle.PicklingError: Can't pickle <class 'function'>: attribute lookup builtins.function failed

オブジェクト階層の選択可能性をテストするために使用できる合理的な方法はありますか? 私の目的は、問題のある機能の場所を見つけることです

4

3 に答える 3

10

これを行うには、 Python でほとんど何でもシリアル化できるdillを使用します。Dill には、コードが失敗したときに pickle 化が失敗する原因を理解するのに役立ついくつかの優れたツールもあります。

>>> import dill
>>> dill.loads(dill.dumps(your_bad_object))
>>> ...
>>> # if you get a pickling error, use dill's tools to figure out a workaround
>>> dill.detect.badobjects(your_bad_object, depth=0)
>>> dill.detect.badobjects(your_bad_object, depth=1)
>>> ...

絶対に必要な場合は、ディルbadobjects(または他の検出関数の 1 つ) を使用して、オブジェクトの参照チェーンに再帰的に飛び込み、上記のようにすべての深さで呼び出す代わりに、ピクルできないオブジェクトをポップアウトできます。

また、objgraphは、テスト スイートに対する非常に便利な補完物でもあります。

>>> # visualize the references in your bad objects
>>> objgraph.show_refs(your_bad_object, filename='your_bad_object.png')
于 2013-10-14T15:41:51.100 に答える
3

私はこれをしました、それは私にとって多くの場合トリックを行います...完全に確実なものを見つけたら、これを更新します

一連のプリントを作成し、例外が発生する場合は例外を発生させるため、オブジェクト階層のどの部分が問題を引き起こしているかを確認できます。

def test_pickle(xThing,lTested = []):
    import pickle
    if id(xThing) in lTested:
        return lTested
    sType = type(xThing).__name__
    print('Testing {0}...'.format(sType))

    if sType in ['type','int','str']:
        print('...too easy')
        return lTested
    if sType == 'dict':
        print('...testing members')
        for k in xThing:
            lTested = Pickalable.test_pickle(xThing[k],lTested)
        print('...tested members')
        return lTested
    if sType == 'list':
        print('...testing members')
        for x in xThing:
            lTested = Pickalable.test_pickle(x)
        print('...tested members')
        return lTested

    lTested.append(id(xThing))
    oClass = type(xThing)

    for s in dir(xThing):
        if s.startswith('_'):
            print('...skipping *private* thingy')
            continue
        #if it is an attribute: Skip it
        try:
            xClassAttribute = oClass.__getattribute__(oClass,s)
        except AttributeError:
            pass
        else:
            if type(xClassAttribute).__name__ == 'property':
                print('...skipping property')
                continue

        xAttribute = xThing.__getattribute__(s)
        print('Testing {0}.{1} of type {2}'.format(sType,s,type(xAttribute).__name__))
        #if it is a function make sure it is stuck to the class...
        if type(xAttribute).__name__ == 'function':
            raise Exception('ERROR: found a function')
        if type(xAttribute).__name__ == 'method':
            print('...skipping method')
            continue
        if type(xAttribute).__name__ == 'HtmlElement':
            continue
        if type(xAttribute) == dict:
            print('...testing dict values for {0}.{1}'.format(sType,s))
            for k in xAttribute:
                lTested = Pickalable.test_pickle(xAttribute[k])
                continue
            print('...finished testing dict values for {0}.{1}'.format(sType,s))

        try:
            oIter = xAttribute.__iter__()
        except AttributeError:
            pass
        except AssertionError:
            pass #lxml elements do this
        else:
            print('...testing iter values for {0}.{1} of type {2}'.format(sType,s,type(xAttribute).__name__))
            for x in xAttribute:   
                lTested = Pickalable.test_pickle(x,lTested)
            print('...finished testing iter values for {0}.{1}'.format(sType,s))

        try:
            xAttribute.__dict__
        except AttributeError:
            pass
        else:
            #this attribute should be explored seperately...
            lTested = Pickalable.test_pickle(xAttribute,lTested)
            continue
        pickle.dumps(xAttribute)


    print('Testing {0} as complete object'.format(sType))
    pickle.dumps(xThing)
    return lTested   
于 2012-12-13T10:48:24.273 に答える