如何检查对象是否可拾取

Bit*_*ise 13 python pickle

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

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

我看到这篇文章,但它没有回答我的问题.

Mik*_*rns 15

中的dill.pickles方法就是这样做的.dill

>>> class Foo(object):
...   x = iter([1,2,3])
... 
>>> f = Foo()     
>>> 
>>> dill.pickles(f)
False
Run Code Online (Sandbox Code Playgroud)

我们可以使用方法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__']
Run Code Online (Sandbox Code Playgroud)

So, the only thing that's failing that's not a "built-in" method of the class is x… so that's a good place to start. Let's check 'x', then replace it with something else if it's the problem.

>>> dill.pickles(Foo.x)
False
>>> Foo.x = xrange(1,4)
>>> dill.pickles(Foo.x)
True
Run Code Online (Sandbox Code Playgroud)

Yep, x was causing a failure, and replacing it with an xrange works because dill can pickle an xrange. What's left to do?

>>> dill.detect.badtypes(f, depth=1).keys()
[]
>>> dill.detect.badtypes(f, depth=1)       
{}
>>> dill.pickles(f)                 
True
>>> 
Run Code Online (Sandbox Code Playgroud)

Apparently (likely because references to x in the class __dict__ now pickle), f now pickles… so we are done.

dill also provides trace to show the exact path in pickling the object.

>>> 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
Run Code Online (Sandbox Code Playgroud)


Max*_*chi 6

dill允许酸洗更多内置的东西pickle

我认为这应该做你想做的事:

def is_picklable(obj):
  try:
    pickle.dumps(obj)

  except pickle.PicklingError:
    return False
  return True
Run Code Online (Sandbox Code Playgroud)


luk*_*k32 5

在这种情况下,我建议进行鸭子测试。尝试将您认为合适的pickle转换为临时文件或内存文件,如果失败则丢弃结果,如果成功重命名。

为什么?

在python中,您可以通过两种方式检查对象是否具有某些属性。

检查 object 是否是某个Abstract Base Class的实例。例如Number“数字层次结构的根。如果您只想检查参数 x 是否为数字,而不关心是什么类型,请使用 isinstance(x, Number)”。

或者尝试一下,然后处理异常。这发生在许多场合。pythonic 哲学基于duck鸭子打字鸭子测试EAFP是关键字。

我什至相信在社区部分的压力下,python3 已经正确地引入了第一个,而许多人仍然坚信duck是使用 python 的方法。

AFAIK 没有可以检查的特殊先决条件,也没有任何ABC可以在酸洗的情况下检查的对象。所以剩下的就是duck

也许可以尝试其他一些东西,但可能不值得。很难对物体进行人工内省,以初步确定它是否适合酸洗。