Python 的 pickle(我这里说的是标准 Python 2.5/2.6/2.7)不能 pickle 锁、文件对象等。
它也不能 pickle 生成器和 lambda 表达式(或任何其他匿名代码),因为 pickle 实际上只存储名称引用。
如果存在锁和依赖于操作系统的功能,原因如下:why你不能腌制它们,这是显而易见的,也是有道理的。
But 为什么不能 pickle 生成器?
Note:只是为了清楚起见 - 我对根本原因感兴趣(或设计决策中的假设和选择)why,而不是“因为它会给你一个 Pickle 错误”。
我意识到这个问题有点宽泛,所以这里有一个经验法则来判断你是否回答这个问题:“如果提出这些假设,或者允许的发电机类型在某种程度上受到更多限制,酸洗发电机会再次工作吗?”
有很多关于此的信息。有关该问题的“官方说法”,请阅读(已关闭)Python bugtracker 问题 http://bugs.python.org/issue1092962.
做出该决定的人之一详细阐述了核心推理这个博客 http://peadrop.com/blog/2009/12/29/why-you-cannot-pickle-generators/:
由于生成器本质上是一个增强的函数,因此我们需要保存它的字节码(这不能保证在 Python 版本之间向后兼容)及其框架(保存生成器的状态,例如局部变量、闭包和指令指针。后者实现起来相当麻烦,因为它基本上需要使整个解释器变得可腌制。因此,任何对 pickling 生成器的支持都需要对 CPython 的核心进行大量更改。
现在,如果 pickle 不支持的对象(例如,文件句柄、套接字、数据库连接等)出现在生成器的局部变量中,则该生成器无法自动 pickle,无论我们可能对生成器有任何 pickle 支持如何实施。因此,在这种情况下,您仍然需要提供自定义__getstate__
and __setstate__
方法。这个问题使得对生成器的任何酸洗支持都相当有限。
并提到了两个建议的解决方法:
不管怎样,如果你需要这样的功能,那么可以看看 Stackless Python,它可以完成上述所有功能。由于 Stackless 的解释器是可挑选的,因此您还可以免费获得流程迁移。这意味着您可以中断一个tasklet(Stackless 绿色线程的名称),对其进行pickle,将pickle 发送到另一台机器,取消pickle,恢复tasklet,然后瞧,您刚刚迁移了一个进程。这是一个非常酷的功能!
但以我的拙见,解决这个问题的最佳解决方案是将生成器重写为简单的迭代器(即带有__next__
方法)。迭代器在空间上可以轻松高效地进行 pickle,因为它们的状态是明确的。然而,您仍然需要显式地处理表示某些外部状态的对象;你无法回避这个问题。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)