我有一个我想要腌制的各种类型的对象列表。我想只腌制那些可腌制的。有没有一种标准的方法来检查一个物体是否是可拾取的类型,而不是试图腌制它?
文档说如果发生酸洗异常,可能已经将一些字节写入文件,因此尝试将对象作为测试进行挑选似乎不是一个好的解决方案。
我看到了this post,但它没有回答我的问题。
答案 0 :(得分:13)
dill
package中的dill.pickles
方法可以做到这一点。
>>> class Foo(object):
... x = iter([1,2,3])
...
>>> f = Foo()
>>>
>>> dill.pickles(f)
False
我们可以使用dill
中的方法来查找导致失败的原因。
>>> dill.detect.badtypes(f)
<class '__main__.Foo'>
>>> dill.detect.badtypes(f, depth=1)
{'__setattr__': <type 'method-wrapper'>, '__reduce_ex__': <type 'builtin_function_or_method'>, '__reduce__': <type 'builtin_function_or_method'>, '__str__': <type 'method-wrapper'>, '__format__': <type 'builtin_function_or_method'>, '__getattribute__': <type 'method-wrapper'>, '__class__': <type 'type'>, '__delattr__': <type 'method-wrapper'>, '__subclasshook__': <type 'builtin_function_or_method'>, '__repr__': <type 'method-wrapper'>, '__hash__': <type 'method-wrapper'>, 'x': <type 'listiterator'>, '__sizeof__': <type 'builtin_function_or_method'>, '__init__': <type 'method-wrapper'>}
>>> dill.detect.badtypes(f, depth=1).keys()
['__setattr__', '__reduce_ex__', '__reduce__', '__str__', '__format__', '__getattribute__', '__class__', '__delattr__', '__subclasshook__', '__repr__', '__hash__', 'x', '__sizeof__', '__init__']
所以,唯一失败的不是这个类的“内置”方法是x
...所以这是一个很好的起点。让我们检查'x',然后用其他东西替换它,如果这是问题。
>>> dill.pickles(Foo.x)
False
>>> Foo.x = xrange(1,4)
>>> dill.pickles(Foo.x)
True
是的,x
导致失败,并将其替换为xrange
,因为dill
可以挑选xrange
。还剩下什么?
>>> dill.detect.badtypes(f, depth=1).keys()
[]
>>> dill.detect.badtypes(f, depth=1)
{}
>>> dill.pickles(f)
True
>>>
显然(可能因为类x
中对__dict__
的引用现在发痒),f
现在发痒......所以我们已经完成了。
dill
还提供trace
来显示腌制对象的确切路径。
>>> dill.detect.trace(True)
>>> dill.pickles(f)
T2: <class '__main__.Foo'>
F2: <function _create_type at 0x10e79b668>
T1: <type 'type'>
F2: <function _load_type at 0x10e79b5f0>
T1: <type 'object'>
D2: <dict object at 0x10e7c6168>
Si: xrange(1, 4)
F2: <function _eval_repr at 0x10e79bcf8>
D2: <dict object at 0x10e7c6280>
True
答案 1 :(得分:3)
在这种情况下,我建议 duck 测试。尝试挑选一个临时文件或一个内存文件,如你认为合适,如果失败则丢弃结果,如果它成功重命名。
<强>为什么吗
在python中,您可以通过两种方式检查对象是否具有某些属性。
检查对象是否是某个Abstract Base Class的实例。例如。 Number
“数字层次结构的根。如果你只是想检查一个参数x是一个数字,而不关心什么类型,请使用isinstance(x,Number)。”
或者尝试然后处理异常。这种情况发生在很多场合。 pythonic philosopy以 duck 为基础。 Duck typing,duck test和EAFP是关键字。
我甚至认为第一个已经在社区的压力下与python3一起正确引入,而许多人仍然坚信 duck 是使用python的方式。
AFAIK没有可以检查的特殊前提条件,也没有任何ABC
可以检查该对象以防酸洗。所以剩下的就是 duck 。
也许可以尝试别的东西,但可能它不值得。要对物体进行手动内省以便初步了解是否适合酸洗是非常困难的。
答案 2 :(得分:1)
dill
允许酸洗内置pickle
中的更多东西。
我认为这应该做您想做的事
def is_picklable(obj):
try:
pickle.dumps(obj)
except pickle.PicklingError:
return False
return True