我有一个我想要腌制的各种类型的对象的列表。我只想腌制那些可腌制的。除了尝试腌制之外,是否有标准方法来检查对象是否为可腌制类型?
文档说,如果发生酸洗异常,它可能已经在一些字节被写入文件之后,所以尝试酸洗对象作为测试似乎不是一个好的解决方案。
我看到了这篇文章,但它没有回答我的问题。
>>> 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
在这种情况下,我会建议进行鸭子测试。尝试pickle到一个临时文件或内存文件中,如果你觉得合适,那么如果失败则丢弃结果,如果成功则重命名。
为什么?
在 python 中,您可以通过两种方式检查对象是否具有某些属性。
检查 object 是否是某个Abstract Base Class的实例。例如Number
“数字层次结构的根。如果您只想检查参数 x 是否为数字,而不关心是什么类型,请使用 isinstance(x, Number)。”
或者尝试一下,然后处理异常。这发生在很多场合。蟒蛇哲学是基于鸭子的。Duck typing、duck test和EAFP是关键字。
我什至相信,在社区的压力下,python3 已经正确引入了第一个,而许多人仍然坚信鸭子是使用 python 的方式。
AFAIK 没有可以检查的特殊先决条件,也没有ABC
在酸洗的情况下可以检查任何该对象。所以剩下的就是鸭子了。
也许可以尝试其他东西,但可能不值得。对物体进行人工自省以初步确定它是否适合酸洗是非常困难的。
dill
允许腌制更多内置的东西pickle
。
这应该做你做什么,我认为:
def is_picklable(obj):
try:
pickle.dumps(obj)
except pickle.PicklingError:
return False
return True