Python 调试泡菜
我正在尝试pickle一个相当复杂的对象层次结构并获得异常:Python 调试泡菜,python,pickle,python-3.2,Python,Pickle,Python 3.2,我正在尝试pickle一个相当复杂的对象层次结构并获得异常: pickle.PicklingError: Can't pickle <class 'function'>: attribute lookup builtins.function failed pickle.PicklingError:无法pickle:属性查找内置函数失败 有没有什么合理的方法可以用来测试对象层次结构的可pickleable性?我的目标是找到有问题的函数的位置我这样做了,它在很多时候都能帮我解决问题。
pickle.PicklingError: Can't pickle <class 'function'>: attribute lookup builtins.function failed
pickle.PicklingError:无法pickle:属性查找内置函数失败
有没有什么合理的方法可以用来测试对象层次结构的可pickleable性?我的目标是找到有问题的函数的位置我这样做了,它在很多时候都能帮我解决问题。。。一旦我找到了完全万无一失的东西,我会更新这个 它生成一组打印,然后如果要引发一个异常,则会引发一个异常,这样您就可以看到对象层次结构的哪个部分导致了问题
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
要做到这一点,我将使用,它可以序列化python中的几乎任何内容。Dill还可以帮助您理解代码失败时是什么导致酸洗失败
>>> 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)
>>> ...
如果您完全愿意,您可以使用dill的badobjects
(或其他检测函数之一)递归地潜入对象的引用链,并弹出不可点击的对象,而不是像上面那样在每个深度调用它
此外,这也是对测试套件的一个非常方便的补充
>>> # visualize the references in your bad objects
>>> objgraph.show_refs(your_bad_object, filename='your_bad_object.png')
这里是@Sheena代码的一个稍加修改的版本,它也适用于python 2和一些其他类型:
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', 'bool', 'NoneType', 'unicode']:
print('...too easy')
return lTested
if sType == 'dict':
print('...testing members')
for k in xThing:
lTested = test_pickle(xThing[k],lTested)
print('...tested members')
return lTested
if sType == 'list':
print('...testing members')
for x in xThing:
lTested = 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, TypeError):
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 type(xAttribute).__name__ == 'function':
print("...skipping function")
continue
if type(xAttribute).__name__ in ['method', 'instancemethod']:
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 = test_pickle(xAttribute[k])
continue
print('...finished testing dict values for {0}.{1}'.format(sType,s))
try:
oIter = xAttribute.__iter__()
except (AttributeError, TypeError):
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 = 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 = test_pickle(xAttribute,lTested)
continue
print(0, xThing, xAttribute)
pickle.dumps(xAttribute)
print('Testing {0} as complete object'.format(sType))
pickle.dumps(xThing)
return lTested
我发现这是最有用的选择(同样是在那些没有pickle的地方,dill更为宽容)。您可以简单地使用
test_pickle(my_complex_object)
print("Done!")
莳萝可能比泡菜强,所以它可以泡菜,泡菜不能泡菜,而我找不到泡菜不能泡菜的。。。。Python2的类似链接。x@acgtyrant-我刚刚用
dill.load()
代替pickle load来调试为什么由pickle.dumps
生成的pickle不能工作。请注意,在测试任何数据帧时,这都会失败<代码>导入熊猫作为pd;test_pickle(pd.DataFrame({'age':[1,2,3]}))给出错误提示,说明在测试任何数据帧时失败<代码>导入熊猫作为pd;test_pickle(pd.DataFrame({'age':[1,2,3]}))给出错误