我对keras
不熟悉,但从文档看来,pickle_safe
只是意味着由生成器产生的元组必须是“可pickle化”的。
pickle
是一个标准的Python模块,用于序列化和反序列化对象。标准的multiprocessing
实现使用pickle
机制在不同的进程之间共享对象——因为这两个进程不共享同一地址空间,所以它们不能直接查看相同的Python对象。因此,为了将对象从进程A发送到进程B,在A中将它们pickled(这样会产生特定格式的字节序列),然后通过进程间通信机制将pickled格式发送到B,最后在B中unpickled,从而在B的地址空间中产生A原始对象的副本。
因此,要发现您的对象是否是可picklable的,只需在它们上面调用pickle.dumps
。
>>> import pickle
>>> class MyObject:
... def __init__(self, a, b, c):
... self.a = a
... self.b = b
... self.c = c
...
>>> foo = MyObject(1, 2, 3)
>>> pickle.dumps(foo)
b'\x80\x03c__main__\nMyObject\nq\x00)\x81q\x01}q\x02(X\x01\x00\x00\x00cq\x03K\x03X\x01\x00\x00\x00aq\x04K\x01X\x01\x00\x00\x00bq\x05K\x02ub.'
>>>
dumps
方法会生成一个字节字符串。现在,我们可以使用 loads
方法从该字节字符串中重新构建对象 foo
作为 bar
:
>>> foo_pick = pickle.dumps(foo)
>>> bar = pickle.loads(foo_pick)
>>> bar
<__main__.MyObject object at 0x7f5e262ece48>
>>> bar.a, bar.b, bar.c
(1, 2, 3)
如果某个东西不可被"pickled",你会收到一个异常。例如,lambda函数是无法被pickled的:
>>> class MyOther:
... def __init__(self, a, b, c):
... self.a = a
... self.b = b
... self.c = c
... self.printer = lambda: print(self.a, self.b, self.c)
...
>>> other = MyOther(1, 2, 3)
>>> other_pick = pickle.dumps(other)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: Can't pickle local object 'MyOther.__init__.<locals>.<lambda>'
请参阅文档以获取更多信息:
https://docs.python.org/3.5/library/pickle.html?highlight=pickle#what-can-be-pickled-and-unpickled
pickle_safe=True
也会抛出错误(至少在我的情况下),因为该对象实际上不是 pickle 安全的。我曾经认为会有某种静默失败的情况。 - SherylHohman