24

我有一个我想要腌制的各种类型的对象的列表。我只想腌制那些可腌制的。除了尝试腌制之外,是否有标准方法来检查对象是否为可腌制类型?

文档说,如果发生酸洗异常,它可能已经在一些字节被写入文件之后,所以尝试酸洗对象作为测试似乎不是一个好的解决方案。

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

4

3 回答 3

27

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

>>> 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
于 2015-08-25T14:36:48.960 回答
6

在这种情况下,我会建议进行鸭子测试。尝试pickle到一个临时文件或内存文件中,如果你觉得合适,那么如果失败则丢弃结果,如果成功则重命名。

为什么?

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

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

或者尝试一下,然后处理异常。这发生在很多场合。蟒蛇哲学是基于鸭子的。Duck typingduck testEAFP是关键字。

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

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

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

于 2013-07-26T04:06:44.280 回答
5

dill允许腌制更多内置的东西pickle

这应该做你做什么,我认为:

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

  except pickle.PicklingError:
    return False
  return True
于 2018-11-20T17:08:43.887 回答