私は非常に複雑なオブジェクト階層をピクルしようとしていますが、例外が発生しています:
pickle.PicklingError: Can't pickle <class 'function'>: attribute lookup builtins.function failed
オブジェクト階層の選択可能性をテストするために使用できる合理的な方法はありますか? 私の目的は、問題のある機能の場所を見つけることです
私は非常に複雑なオブジェクト階層をピクルしようとしていますが、例外が発生しています:
pickle.PicklingError: Can't pickle <class 'function'>: attribute lookup builtins.function failed
オブジェクト階層の選択可能性をテストするために使用できる合理的な方法はありますか? 私の目的は、問題のある機能の場所を見つけることです
これを行うには、 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')
私はこれをしました、それは私にとって多くの場合トリックを行います...完全に確実なものを見つけたら、これを更新します
一連のプリントを作成し、例外が発生する場合は例外を発生させるため、オブジェクト階層のどの部分が問題を引き起こしているかを確認できます。
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