Python 为什么酸洗tensorflow张量会失败?

Python 为什么酸洗tensorflow张量会失败?,python,tensorflow,serialization,pickle,dill,Python,Tensorflow,Serialization,Pickle,Dill,下面是一个片段,它将成功地用dill序列化,但用pickle序列化失败。令人惊讶的是,Tensor对象不是本机可pickle的。这是线程感知张量的一个基本限制,还是只是没有实现 import dill import pickle import tensorflow as tf dill.dumps(tf.zeros((1,1))) print("Dill succeeded") pickle.dumps(tf.zeros((1,1))) print("Pickle succeeded") 输

下面是一个片段,它将成功地用
dill
序列化,但用
pickle
序列化失败。令人惊讶的是,
Tensor
对象不是本机可pickle的。这是线程感知张量的一个基本限制,还是只是没有实现

import dill
import pickle
import tensorflow as tf

dill.dumps(tf.zeros((1,1)))
print("Dill succeeded")
pickle.dumps(tf.zeros((1,1)))
print("Pickle succeeded")
输出:

$ python foo.py
Dill succeeded
Traceback (most recent call last):
  File "foo.py", line 7, in <module>
    pickle.dumps(tf.zeros((1,1)))
TypeError: can't pickle _thread.lock objects
$python foo.py
迪尔成功了
回溯(最近一次呼叫最后一次):
文件“foo.py”,第7行,在
pickle.dumps(tf.zeros((1,1)))
TypeError:无法pickle\u thread.lock对象

为什么dill可以序列化这些对象,而不是pickle?简单的回答是,
pickle
无法序列化python中的大多数对象,包括
thread.lock
对象。如果要序列化其中一个对象,请使用高级序列化库,如
dill
。至于
pickle
不能的确切原因,我认为最初它源于GIL和
frame
对象的实现,使得一些对象不可序列化,因此没有动力序列化语言中的所有内容。关于所有python对象的序列化所产生的安全问题,人们一直在谈论,但我认为这是一个转移视线的问题。没有完整的语言序列化限制了并行计算的操作能力,因此希望
pickle
能够从
dill
学习如何序列化更多的对象。

我发现我无法重现脚本的输出,并且
dill
pickle
的序列化都失败

虽然这个问题已经有好几年了,但我相信问题不在于pickle,而在于tensorflow 1.x中的张量不是立即计算的。而是在执行图形时对其进行求值。(在tensorflow 2.0中,默认情况下启用了急切执行,因此您实际上不必处理此范例)

使用
tf.enable\u eager\u execution()
或在
tf.Session()上下文中计算张量

使用Pickle或Dill时,以下脚本不会引发错误:

将tensorflow导入为tf
tf.enable_eager_execution()
进口泡菜
#进口莳萝
n=tf.零((1,1))
泡菜倾倒区(n)
#莳萝倾倒(n)
打印(‘成功’)
使用Session.run()的相同脚本不会引发错误:

将tensorflow导入为tf
进口泡菜
#进口莳萝
使用tf.Session()作为sess:
n=sess.run(tf.zeros((1,1)))
泡菜倾倒区(n)
#莳萝倾倒(n)
打印(‘成功’)

可能重复如果查看回溯,很明显,
对象没有酸洗。请注意,当您说函数没有立即求值时,这意味着它们被放在执行堆栈上,这意味着有一个到
对象的连接,如我的回答中所述。自从OP发布以来,
dill
Tensor
对象都有了很大的发展。嗨@MikeMcKerns,虽然我不完全熟悉tensorflow的内部工作原理,也不完全熟悉它是如何使用
frame
对象的,但我是根据tf.Tensor的文档来回答的。构建上下文中的tf.Tensor实际上并不包含该Tensor的值,而是tensorflow操作输出的句柄。由于它不是Python对象,我认为除非对它求值,否则它是可序列化的是没有意义的。。。组成python函数的对象在函数第一次求值之前和之后是不同的。通过延迟求值,python函数的框架在构建时就已经组成,但是直到第一次调用它时才处理它的内容。在此之前,函数的核心被放在执行堆栈上(基本上是在
帧上),以便在调用时检索。另外,请注意,python中的所有内容本质上都是一个对象——一个列表、一个文件句柄。。。基本上,任何具有
类型的内容(即,派生自python类)。@MikeMcKerns我希望您不介意我再问一些问题,因为您似乎非常熟悉这个主题。在这种情况下,调用调用TysFooS+C++ API时,TunSoRoSO不重要吗?事实上,<>代码>框架>代码>似乎是一个C++结构。Python对象通常是围绕C类型对象的瘦类——除非你直接调用一个<代码> cType < /C>(如果我没有错的话)。所以,我必须看看如何调用
tensorflow
C-type api。你没有用dill库提供tf-tensor序列化的证据。@denfromufa:OP不是这样问的。在你看来,除了OP在问题中所做的以外,我还应该展示什么呢?我现在明白了,很抱歉搞混了!