如何检查对象是否可拾取

时间:2013-07-26 02:47:52

标签: python pickle

我有一个我想要腌制的各种类型的对象列表。我想只腌制那些可腌制的。有没有一种标准的方法来检查一个物体是否是可拾取的类型,而不是试图腌制它?

文档说如果发生酸洗异常,可能已经将一些字节写入文件,因此尝试将对象作为测试进行挑选似乎不是一个好的解决方案。

我看到了this post,但它没有回答我的问题。

3 个答案:

答案 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 typingduck testEAFP是关键字。

我甚至认为第一个已经在社区的压力下与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