我有一个对象列表,其中包含不同类型的对象,我想对它们进行pickle。我只想pickle可pickle的对象。是否有一种标准方法可以检查对象是否为可pickle类型,而不是尝试pickle它?
文档说明如果发生pickling异常,则可能已经写入文件的某些字节后,尝试将对象pickle作为测试似乎不是一个好的解决方案。
我看到了这个帖子,但它没有回答我的问题。
在dill
包中有一个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
可以pickle xrange
。还剩下什么要做吗?
>>> dill.detect.badtypes(f, depth=1).keys()
[]
>>> dill.detect.badtypes(f, depth=1)
{}
>>> dill.pickles(f)
True
>>>
显然(很可能是因为在类__dict__
中引用了x
,现在能够pickle),f
现在也能pickle了...因此我们完成了。
dill
还提供了trace
来显示在pickling对象时的确切路径。
>>> 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
F2
或 D1
这样的标记时,都会打开另一个“子对象”以供检查,并且在实际 pickled 对象时有类似的关闭标记。 - Mike McKerns或者先尝试它,然后处理异常。这在许多情况下发生。Pythonic哲学是基于鸭子的。 鸭子类型, 鸭子测试, 和 EAFP 是关键词。
我甚至相信,在社区的一部分的压力下,第一个已经在Python3中得到了适当的介绍,而许多人仍然坚信鸭子是使用Python的方法。
AFAIK没有特殊的预条件可以检查,在pickle的情况下也没有任何ABC
可以检查对象是否符合要求。所以剩下的就是鸭子。
try: mock = iter(data[0]) except TypeError:
。这与某些 Python 的方式相当不同,因为理想情况下我应该将其视为可迭代并继续传递。然而,这种方法有一个严重的缺点,就是错误弹出的位置太低,很难找到它们。从我在文档中读到的内容来看,Python 使用其内部知识来 pickle 对象。这不像 __str__
。你可以在奇怪的情况下提供一些帮助程序,但并不是每个地方都需要。我没有找到其他可靠的方法。 - luk32isPickleable()
可能需要解决停机问题。 - Schilcotedill
可以比内置的 pickle
库更好地支持对象序列化。
我认为以下代码可以实现你的需求:
def is_picklable(obj):
try:
pickle.dumps(obj)
except pickle.PicklingError:
return False
return True
except TypeError
。 - Elazarexcept TypeError
。 - undefined
dill.pickles(f)
提供的你所需要的功能呢? - Charlie Parker